[med-svn] [kronatools] 01/02: Imported Upstream version 2.7+dfsg

Andreas Tille tille at debian.org
Wed Jul 27 14:19:58 UTC 2016


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

tille pushed a commit to branch master
in repository kronatools.

commit c399c452b7706b801861eed233175e2819420f46
Author: Andreas Tille <tille at debian.org>
Date:   Wed Jul 27 16:14:23 2016 +0200

    Imported Upstream version 2.7+dfsg
---
 KronaTools/LICENSE.txt                           |   86 +
 KronaTools/README.txt                            |    8 +
 KronaTools/data/README                           |   26 +
 KronaTools/data/ec.tsv                           | 6983 ++++++++++++++++++++++
 KronaTools/deployResources.sh                    |   43 +
 KronaTools/img/favicon.ico                       |  Bin 0 -> 7886 bytes
 KronaTools/img/favicon.uri                       |    1 +
 KronaTools/img/hidden.png                        |  Bin 0 -> 449 bytes
 KronaTools/img/hidden.uri                        |    1 +
 KronaTools/img/loading.uri                       |    1 +
 KronaTools/img/logo-med.png                      |  Bin 0 -> 52836 bytes
 KronaTools/img/logo-med.uri                      |    1 +
 KronaTools/img/logo-small.png                    |  Bin 0 -> 4340 bytes
 KronaTools/img/logo-small.uri                    |    1 +
 KronaTools/img/logo.png                          |  Bin 0 -> 4481 bytes
 KronaTools/img/logo.uri                          |    1 +
 KronaTools/install.pl                            |  132 +
 KronaTools/lib/KronaTools.pm                     | 2361 ++++++++
 KronaTools/scripts/ClassifyBLAST.pl              |  141 +
 KronaTools/scripts/ClassifyBLAST_hash.pl         |  232 +
 KronaTools/scripts/GetContigMagnitudes.pl        |   55 +
 KronaTools/scripts/GetContigMagnitudesCONTIG.pl  |   59 +
 KronaTools/scripts/GetContigMagnitudesNewbler.pl |   60 +
 KronaTools/scripts/GetLCA.pl                     |  117 +
 KronaTools/scripts/GetLibPath.pl                 |   13 +
 KronaTools/scripts/GetTaxIDFromAcc.pl            |  112 +
 KronaTools/scripts/GetTaxInfo.pl                 |   86 +
 KronaTools/scripts/ImportAmphora.pl              |  248 +
 KronaTools/scripts/ImportBLAST.pl                |  175 +
 KronaTools/scripts/ImportDiskUsage.pl            |  214 +
 KronaTools/scripts/ImportEC.pl                   |  251 +
 KronaTools/scripts/ImportFCP.pl                  |  138 +
 KronaTools/scripts/ImportGalaxy.pl               |  149 +
 KronaTools/scripts/ImportKrona.pl                |  138 +
 KronaTools/scripts/ImportMETAREP-EC.pl           |  141 +
 KronaTools/scripts/ImportMETAREP-blast.pl        |  218 +
 KronaTools/scripts/ImportMGRAST.pl               |  157 +
 KronaTools/scripts/ImportPHMMER.pl               |  261 +
 KronaTools/scripts/ImportPhymmBL.pl              |  223 +
 KronaTools/scripts/ImportRDP.pl                  |  207 +
 KronaTools/scripts/ImportRDPComparison.pl        |  182 +
 KronaTools/scripts/ImportTaxonomy.pl             |  263 +
 KronaTools/scripts/ImportText.pl                 |  123 +
 KronaTools/scripts/ImportXML.pl                  |   77 +
 KronaTools/scripts/accession2taxid.make          |   32 +
 KronaTools/scripts/diffCombine.pl                |   37 +
 KronaTools/scripts/differentiate.pl              |  127 +
 KronaTools/scripts/extractNodeData.pl            |   20 +
 KronaTools/scripts/extractTaxonomy.pl            |   95 +
 KronaTools/scripts/formatEC.pl                   |   59 +
 KronaTools/scripts/getContigMagnitudesCA.pl      |   63 +
 KronaTools/scripts/indexGIs.pl                   |   81 +
 KronaTools/scripts/taxonomy.make                 |   23 +
 KronaTools/src/krona-1.1.js                      | 5983 ++++++++++++++++++
 KronaTools/src/krona-2.0.js                      | 6597 ++++++++++++++++++++
 KronaTools/updateAccessions.sh                   |   11 +
 KronaTools/updateTaxonomy.sh                     |  311 +
 57 files changed, 27124 insertions(+)

diff --git a/KronaTools/LICENSE.txt b/KronaTools/LICENSE.txt
new file mode 100644
index 0000000..34f5047
--- /dev/null
+++ b/KronaTools/LICENSE.txt
@@ -0,0 +1,86 @@
+PURPOSE
+
+Krona is a flexible tool for exploring the relative proportions of
+hierarchical data, such as metagenomic classifications, using a
+radial, space-filling display. It is implemented using HTML5 and
+JavaScript, allowing charts to be explored locally or served over the
+Internet, requiring only a current version of any major web
+browser. Krona charts can be created using an Excel template or from
+common bioinformatic formats using the provided conversion scripts.
+
+
+COPYRIGHT LICENSE
+
+Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+Adam Phillippy
+
+This Software was prepared for the Department of Homeland Security
+(DHS) by the Battelle National Biodefense Institute, LLC (BNBI) as
+part of contract HSHQDC-07-C-00020 to manage and operate the National
+Biodefense Analysis and Countermeasures Center (NBACC), a Federally
+Funded Research and Development Center.
+
+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 Battelle National Biodefense Institute 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
+HOLDER 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.
+
+
+TRADEMARK LICENSE
+
+KRONA™ is a trademark of the Department of Homeland Security, and use
+of the trademark is subject to the following conditions:
+
+* Distribution of the unchanged, official code/software using the
+  KRONA™ mark is hereby permitted by the Department of Homeland
+  Security, provided that the software is distributed without charge
+  and modification.
+
+* Distribution of altered source code/software using the KRONA™ mark
+  is not permitted unless written permission has been granted by the
+  Department of Homeland Security.
+
+
+PATENTS
+
+The Krona software is not eligible for patent because there have been
+previous and open implementations of this visualization method since
+the year 2000 (e.g. "Focus+context display and navigation techniques
+for enhancing radial, space-filling hierarchy visualizations." Stasko,
+J. and Zhang, E. InfoVis, 2000). Krona represents a reimplementation and
+application of an existing method to the new domain of
+metagenomics. BNBI, as the copyright holders, wish to release Krona
+freely and openly as a service to the bioinformatics community.
+
+
+POINT OF CONTACT
+
+Todd Harrington
+General Counsel
+Battelle National Biodefense Institute
+harringtont at nbacc.net
+
diff --git a/KronaTools/README.txt b/KronaTools/README.txt
new file mode 100644
index 0000000..97b8461
--- /dev/null
+++ b/KronaTools/README.txt
@@ -0,0 +1,8 @@
+For installation and usage instructions please refer to:
+https://github.com/marbl/Krona/wiki/KronaTools
+
+Tool names start with 'kt' (use TAB for completions) and can be run without
+arguments to list options.
+
+For feedback please see:
+https://github.com/marbl/Krona/issues
diff --git a/KronaTools/data/README b/KronaTools/data/README
new file mode 100644
index 0000000..64ed34a
--- /dev/null
+++ b/KronaTools/data/README
@@ -0,0 +1,26 @@
+ec.tsv
+======
+
+This file is a list of short names of all Enzyme Commission categories.  It was
+generated from data downloaded from the Integrated Microbial Genomes Human
+Microbiome Project.  To recreate this file:
+
+- Download the tab-delimited list of EC names:
+  - Navigate to:
+    http://www.hmpdacc-resources.org/cgi-bin/imgm_hmp/main.cgi?section=FindFunctions&page=enzymeList
+  - Choose "Select All"
+  - Choose "Export"
+
+- Run:
+  <KronaTools>/scripts/formatEC.pl <download_file> > <output>
+
+The formatEC.pl script converts the format so it is easier to parse and removes
+redundant descriptions from group names. For example:
+
+  EC:1.-	Oxidoreductases.
+  EC:1.1.-	Oxidoreductases. Acting on the CH-OH group of donors.
+
+...becomes:
+
+  1	Oxidoreductases
+  1.1	Acting on the CH-OH group of donors
diff --git a/KronaTools/data/ec.tsv b/KronaTools/data/ec.tsv
new file mode 100644
index 0000000..e58ec92
--- /dev/null
+++ b/KronaTools/data/ec.tsv
@@ -0,0 +1,6983 @@
+1	Oxidoreductases
+1.1	Acting on the CH-OH group of donors
+1.1.1	With NAD(+) or NADP(+) as acceptor
+1.1.2	With a cytochrome as acceptor
+1.1.3	With oxygen as acceptor
+1.1.4	With a disulfide as acceptor
+1.1.5	With a quinone or similar compound as acceptor
+1.1.9	With a copper protein as acceptor
+1.1.98	With other, known, acceptors
+1.1.99	With other acceptors
+1.2	Acting on the aldehyde or oxo group of donors
+1.2.1	With NAD(+) or NADP(+) as acceptor
+1.2.2	With a cytochrome as acceptor
+1.2.3	With oxygen as acceptor
+1.2.4	With a disulfide as acceptor
+1.2.5	With a quinone or similar compound as acceptor
+1.2.7	With an iron-sulfur protein as acceptor
+1.2.98	With other, known, acceptors
+1.2.99	With other acceptors
+1.3	Acting on the CH-CH group of donors
+1.3.1	With NAD(+) or NADP(+) as acceptor
+1.3.2	With a cytochrome as acceptor
+1.3.3	With oxygen as acceptor
+1.3.4	With a disulfide as acceptor
+1.3.5	With a quinone or related compound as acceptor
+1.3.7	With an iron-sulfur protein as acceptor
+1.3.8	With a flavin as acceptor
+1.3.98	With other, known, acceptors
+1.3.99	With other acceptors
+1.4	Acting on the CH-NH(2) group of donors
+1.4.1	With NAD(+) or NADP(+) as acceptor
+1.4.2	With a cytochrome as acceptor
+1.4.3	With oxygen as acceptor
+1.4.4	With a disulfide as acceptor
+1.4.5	With a quinone or similar compound as acceptor
+1.4.7	With an iron-sulfur protein as acceptor
+1.4.9	With a copper protein as acceptor
+1.4.98	With other, known, acceptors
+1.4.99	With other acceptors
+1.5	Acting on the CH-NH group of donors
+1.5.1	With NAD(+) or NADP(+) as acceptor
+1.5.3	With oxygen as acceptor
+1.5.4	With a disulfide as acceptor
+1.5.5	With a quinone or similar compound as acceptor
+1.5.7	With an iron-sulfur protein as acceptor
+1.5.8	With a flavin as acceptor
+1.5.98	With other, known, acceptors
+1.5.99	With other acceptors
+1.6	Acting on NADH or NADPH
+1.6.1	With NAD(+) or NADP(+) as acceptor
+1.6.2	With a heme protein as acceptor
+1.6.3	With oxygen as acceptor
+1.6.4	With a disulfide as acceptor
+1.6.5	With a quinone or similar compound as acceptor
+1.6.6	With a nitrogenous group as acceptor
+1.6.7	With a iron-sulfur protein as acceptor
+1.6.8	With a flavin as acceptor
+1.6.99	With other acceptors
+1.7	Acting on other nitrogenous compounds as donors
+1.7.1	With NAD(+) or NADP(+) as acceptor
+1.7.2	With a cytochrome as acceptor
+1.7.3	With oxygen as acceptor
+1.7.5	With a quinone or similar compound as acceptor
+1.7.6	With a nitrogenous group as acceptor
+1.7.7	With an iron-sulfur protein as acceptor
+1.7.9	With a copper protein as acceptor
+1.7.99	With other acceptors
+1.8	Acting on a sulfur group of donors
+1.8.1	With NAD(+) or NADP(+) as acceptor
+1.8.2	With a cytochrome as acceptor
+1.8.3	With oxygen as acceptor
+1.8.4	With a disulfide as acceptor
+1.8.5	With a quinone or similar compound as acceptor
+1.8.6	With an nitrogenous group as acceptor
+1.8.7	With an iron-sulfur protein as acceptor
+1.8.98	With other, known, acceptors
+1.8.99	With other acceptors
+1.9	Acting on a heme group of donors
+1.9.3	With oxygen as acceptor
+1.9.6	With a nitrogenous group as acceptor
+1.9.98	With other, known, acceptors
+1.9.99	With other acceptors
+1.10	Acting on diphenols and related substances as donors
+1.10.1	With NAD(+) or NADP(+) as acceptor
+1.10.2	With a cytochrome as acceptor
+1.10.3	With oxygen as acceptor
+1.10.5	With a quinone or related compound as acceptor
+1.10.9	With a copper protein as acceptor
+1.10.98	With other, known, acceptors
+1.10.99	With other acceptors
+1.11	Acting on a peroxide as acceptor
+1.11.1	Peroxidases
+1.11.2	With H(2)O(2) as acceptor, one oxygen atom of which is incorporated into the product
+1.12	Acting on hydrogen as donors
+1.12.1	With NAD(+) or NADP(+) as acceptor
+1.12.2	With a cytochrome as acceptor
+1.12.5	With a quinone or similar compound as acceptor
+1.12.7	With an iron-sulfur protein as acceptor
+1.12.98	With other, known, acceptors
+1.12.99	With other acceptors
+1.13	Acting on single donors with incorporation of molecular oxygen (oxygenases). The oxygen incorporated need not be derived from O(2)
+1.13.1	With NADH or NADPH as one donor
+1.13.11	With incorporation of two atoms of oxygen
+1.13.12	With incorporation of one atom of oxygen (internal monooxygenases or internal mixed function oxidases)
+1.13.99	Miscellaneous
+1.14	Acting on paired donors, with incorporation or reduction of molecular oxygen. The oxygen incorporated need not be derived from O(2)
+1.14.1	With NADH or NADPH as one donor
+1.14.2	With ascorbate as one donor
+1.14.3	With reduced pteridine as one donor
+1.14.11	With 2-oxoglutarate as one donor, and incorporation of one atom each of oxygen into both donors
+1.14.12	With NADH or NADPH as one donor, and incorporation of two atoms of oxygen into one donor
+1.14.13	With NADH or NADPH as one donor, and incorporation of one atom of oxygen
+1.14.14	With reduced flavin or flavoprotein as one donor, and incorporation of one atom of oxygen
+1.14.15	With reduced iron-sulfur protein as one donor, and incorporation of one atom of oxygen
+1.14.16	With reduced pteridine as one donor, and incorporation of one atom of oxygen
+1.14.17	With reduced ascorbate as one donor, and incorporation of one atom of oxygen
+1.14.18	With another compound as one donor, and incorporation of one atom of oxygen
+1.14.19	With oxidation of a pair of donors resulting in the reduction of molecular oxygen to two molecules of water
+1.14.20	With 2-oxoglutarate as one donor, and the other dehydrogenated
+1.14.21	With NADH or NADPH as one donor, and the other dehydrogenated
+1.14.99	Miscellaneous
+1.15	Acting on superoxide as acceptor
+1.15.1	Acting on superoxide as acceptor
+1.16	Oxidizing metal ions
+1.16.1	With NAD(+) or NADP(+) as acceptor
+1.16.3	With oxygen as acceptor
+1.16.5	With a quinone or similar compound as acceptor
+1.16.8	With a flavin as acceptor
+1.16.9	With a copper protein as acceptor
+1.16.98	With other known acceptors
+1.17	Acting on CH or CH(2) groups
+1.17.1	With NAD(+) or NADP(+) as acceptor
+1.17.2	With a cytochrome as acceptor
+1.17.3	With oxygen as acceptor
+1.17.4	With a disulfide as acceptor
+1.17.5	With a quinone or similar compound as acceptor
+1.17.7	With an iron-sulfur protein as acceptor
+1.17.98	With other, known, acceptors
+1.17.99	With other acceptors
+1.18	Acting on iron-sulfur proteins as donors
+1.18.1	With NAD(+) or NADP(+) as acceptor
+1.18.2	With dinitrogen as acceptor
+1.18.3	With H(+) as acceptor
+1.18.6	With dinitrogen as acceptor
+1.18.96	With other, known, acceptors
+1.18.99	With H(+) as acceptor
+1.19	Acting on reduced flavodoxin as donor
+1.19.6	With dinitrogen as acceptor
+1.20	Acting on phosphorus or arsenic in donors
+1.20.1	With NAD(+) or NADP(+) as acceptor
+1.20.2	With a cytochrome as acceptor
+1.20.4	With disulfide as acceptor
+1.20.9	With a copper protein as acceptor
+1.20.98	With other, known acceptors
+1.20.99	With other acceptors
+1.21	Catalyzing the reaction X-H + Y-H = 'X-Y'
+1.21.1	With NAD(+) or NADP(+) as acceptor
+1.21.3	With oxygen as acceptor
+1.21.4	With a disulfide as acceptor
+1.21.98	With other, known acceptors
+1.21.99	With other acceptors
+1.22	Acting on halogen in donors
+1.22.1	With NAD(+) or NADP(+) as acceptor
+1.23	Reducing C-O-C group as acceptor
+1.23.1	With NADH or NADPH as donor
+1.23.5	With a quinone or similar compound as acceptor
+1.97	Other oxidoreductases
+1.97.1	Other oxidoreductases
+1.98	Enzymes using H(2) as reductant
+1.98.1	Other oxidoreductases
+1.99	Other enzymes using O(2) as oxidant
+1.99.1	Hydroxylases
+1.99.2	Oxygenases
+2	Transferases
+2.1	Transferring one-carbon groups
+2.1.1	Methyltransferases
+2.1.2	Hydroxymethyl-, formyl- and related transferases
+2.1.3	Carboxy- and carbamoyltransferases
+2.1.4	Amidinotransferases
+2.2	Transferring aldehyde or ketonic groups
+2.2.1	Transketolases and transaldolases
+2.3	Acyltransferases
+2.3.1	Transferring groups other than amino-acyl groups
+2.3.2	Aminoacyltransferases
+2.3.3	Acyl groups converted into alkyl groups on transfer
+2.4	Glycosyltransferases
+2.4.1	Hexosyltransferases
+2.4.2	Pentosyltransferases
+2.4.99	Transferring other glycosyl groups
+2.5	Transferring alkyl or aryl groups, other than methyl groups
+2.5.1	Transferring alkyl or aryl groups, other than methyl groups
+2.6	Transferring nitrogenous groups
+2.6.1	Transaminases
+2.6.2	Amidinotransferases
+2.6.3	Oximinotransferases
+2.6.99	Transferring other nitrogenous groups
+2.7	Transferring phosphorus-containing groups
+2.7.1	Phosphotransferases with an alcohol group as acceptor
+2.7.2	Phosphotransferases with a carboxy group as acceptor
+2.7.3	Phosphotransferases with a nitrogenous group as acceptor
+2.7.4	Phosphotransferases with a phosphate group as acceptor
+2.7.5	Phosphotransferases with regeneration of donors, apparently catalyzing intramolecular transfers
+2.7.6	Diphosphotransferases
+2.7.7	Nucleotidyltransferases
+2.7.8	Transferases for other substituted phosphate groups
+2.7.9	Phosphotransferases with paired acceptors
+2.7.10	Protein-tyrosine kinases
+2.7.11	Protein-serine/threonine kinases
+2.7.12	Dual-specificity kinases (those acting on Ser/Thr and Tyr residues)
+2.7.13	Protein-histidine kinases
+2.7.14	Protein-arginine kinases
+2.7.99	Other protein kinases
+2.8	Transferring sulfur-containing groups
+2.8.1	Sulfurtransferases
+2.8.2	Sulfotransferases
+2.8.3	CoA-transferases
+2.8.4	Transferring alkylthio groups
+2.9	Transferring selenium-containing groups
+2.9.1	Selenotransferases
+2.10	Transferring molybdenum- or tungsten-containing groups
+2.10.1	Molybdenumtransferases or tungstentransferases with sulfide groups as acceptors
+3	Hydrolases
+3.1	Acting on ester bonds
+3.1.1	Carboxylic ester hydrolases
+3.1.2	Thiolester hydrolases
+3.1.3	Phosphoric monoester hydrolases
+3.1.4	Phosphoric diester hydrolases
+3.1.5	Triphosphoric monoester hydrolases
+3.1.6	Sulfuric ester hydrolases
+3.1.7	Diphosphoric monoester hydrolases
+3.1.8	Phosphoric triester hydrolases
+3.1.11	Exodeoxyribonucleases producing 5'-phosphomonoesters
+3.1.12	Exodeoxyribonucleases producing 3'-phosphomonoesters
+3.1.13	Exoribonucleases producing 5'-phosphomonoesters
+3.1.14	Exoribonucleases producing 3'-phosphomonoesters
+3.1.15	Exonucleases active with either ribo- or deoxyribonucleic acids and producing 5'-phosphomonoesters
+3.1.16	Exonucleases active with either ribo- or deoxyribonucleic acids and producing 3'-phosphomonoesters
+3.1.21	Endodeoxyribonucleases producing 5'-phosphomonoesters
+3.1.22	Endodeoxyribonucleases producing other than 5'-phosphomonoesters
+3.1.23	Site specific endodeoxyribonucleases: cleavage is sequence specific
+3.1.24	Site specific endodeoxyribonucleases: cleavage is not sequence specific
+3.1.25	Site-specific endodeoxyribonucleases specific for altered bases
+3.1.26	Endoribonucleases producing 5'-phosphomonoesters
+3.1.27	Endoribonucleases producing other than 5'-phosphomonoesters
+3.1.30	Endoribonucleases active with either ribo- or deoxyribonucleic acids and producing 5'-phosphomonoesters
+3.1.31	Endoribonucleases active with either ribo- or deoxyribonucleic acids and producing 3'-phosphomonoesters
+3.2	Glycosylases
+3.2.1	Glycosidases, i.e. enzymes hydrolyzing O- and S-glycosyl compounds
+3.2.2	Hydrolyzing N-glycosyl compounds
+3.2.3	Hydrolyzing S-glycosyl compounds
+3.3	Acting on ether bonds
+3.3.1	Thioether and trialkylsulfonium hydrolases
+3.3.2	Ether hydrolases
+3.4	Acting on peptide bonds (peptidases)
+3.4.1	alpha-Amino-acyl-peptide hydrolases
+3.4.2	Peptidyl-amino-acid hydrolases
+3.4.3	Dipeptide hydrolases
+3.4.4	Peptidyl peptide hydrolases
+3.4.11	Aminopeptidases
+3.4.12	Peptidylamino-acid hydrolases or acylamino-acid hydrolases
+3.4.13	Dipeptidases
+3.4.14	Dipeptidyl-peptidases and tripeptidyl-peptidases
+3.4.15	Peptidyl-dipeptidases
+3.4.16	Serine-type carboxypeptidases
+3.4.17	Metallocarboxypeptidases
+3.4.18	Cysteine-type carboxypeptidases
+3.4.19	Omega peptidases
+3.4.21	Serine endopeptidases
+3.4.22	Cysteine endopeptidases
+3.4.23	Aspartic endopeptidases
+3.4.24	Metalloendopeptidases
+3.4.25	Threonine endopeptidases
+3.4.99	Endopeptidases of unknown catalytic mechanism
+3.5	Acting on carbon-nitrogen bonds, other than peptide bonds
+3.5.1	In linear amides
+3.5.2	In cyclic amides
+3.5.3	In linear amidines
+3.5.4	In cyclic amidines
+3.5.5	In nitriles
+3.5.99	In other compounds
+3.6	Acting on acid anhydrides
+3.6.1	In phosphorus-containing anhydrides
+3.6.2	In sulfonyl-containing anhydrides
+3.6.3	Acting on acid anhydrides; catalyzing transmembrane movement of substances
+3.6.4	Acting on ATP; involved in cellular and subcellular movement
+3.6.5	Acting on GTP; involved in cellular and subcellular movement
+3.7	Acting on carbon-carbon bonds
+3.7.1	In ketonic substances
+3.8	Acting on halide bonds
+3.8.1	In C-halide compounds
+3.8.2	In P-halide compounds
+3.9	Acting on phosphorus-nitrogen bonds
+3.9.1	Acting on phosphorus-nitrogen bonds
+3.10	Acting on sulfur-nitrogen bonds
+3.10.1	Acting on sulfur-nitrogen bonds
+3.11	Acting on carbon-phosphorus bonds
+3.11.1	Acting on carbon-phosphorus bonds
+3.12	Acting on sulfur-sulfur bonds
+3.12.1	Acting on sulfur-sulfur bonds
+3.13	Acting on carbon-sulfur bonds
+3.13.1	Acting on carbon-sulfur bonds
+4	Lyases
+4.1	Carbon-carbon lyases
+4.1.1	Carboxy-lyases
+4.1.2	Aldehyde-lyases
+4.1.3	Oxo-acid-lyases
+4.1.99	Other carbon-carbon lyases
+4.2	Carbon-oxygen lyases
+4.2.1	Hydro-lyases
+4.2.2	Acting on polysaccharides
+4.2.3	Acting on phosphates
+4.2.99	Other carbon-oxygen lyases
+4.3	Carbon-nitrogen lyases
+4.3.1	Ammonia-lyases
+4.3.2	Lyases acting on amides, amidines, etc
+4.3.3	Amine-lyases
+4.3.99	Other carbon-nitrogen lyases
+4.4	Carbon-sulfur lyases
+4.4.1	Carbon-sulfur lyases
+4.5	Carbon-halide lyases
+4.5.1	Carbon-halide lyases
+4.6	Phosphorus-oxygen lyases
+4.6.1	Phosphorus-oxygen lyases
+4.7	Carbon-phosphorus lyases
+4.7.1	Carbon-phosphorus lyases
+4.99	Other lyases
+4.99.1	Other lyases
+5	Isomerases
+5.1	Racemases and epimerases
+5.1.1	Acting on amino acids and derivatives
+5.1.2	Acting on hydroxy acids and derivatives
+5.1.3	Acting on carbohydrates and derivatives
+5.1.99	Acting on other compounds
+5.2	Cis-trans-isomerases
+5.2.1	Cis-trans isomerases
+5.3	Intramolecular oxidoreductases
+5.3.1	Interconverting aldoses and ketoses
+5.3.2	Interconverting keto- and enol-groups
+5.3.3	Transposing C=C bonds
+5.3.4	Transposing S-S bonds
+5.3.99	Other intramolecular oxidoreductases
+5.4	Intramolecular transferases
+5.4.1	Transferring acyl groups
+5.4.2	Phosphotransferases (phosphomutases)
+5.4.3	Transferring amino groups
+5.4.4	Transferring hydroxy groups
+5.4.99	Transferring other groups
+5.5	Intramolecular lyases
+5.5.1	Intramolecular lyases
+5.99	Other isomerases
+5.99.1	Other isomerases
+6	Ligases
+6.1	Forming carbon-oxygen bonds
+6.1.1	Ligases forming aminoacyl-tRNA and related compounds
+6.1.2	Acid--alcohol ligases (ester synthases)
+6.2	Forming carbon-sulfur bonds
+6.2.1	Acid--thiol ligases
+6.3	Forming carbon-nitrogen bonds
+6.3.1	Acid--ammonia (or amine) ligases (amide synthases)
+6.3.2	Acid--amino-acid ligases (peptide synthases)
+6.3.3	Cyclo-ligases
+6.3.4	Other carbon--nitrogen ligases
+6.3.5	Carbon--nitrogen ligases with glutamine as amido-N-donor
+6.4	Forming carbon-carbon bonds
+6.4.1	Forming carbon-carbon bonds
+6.5	Forming phosphoric ester bonds
+6.5.1	Forming phosphoric ester bonds
+6.6	Forming nitrogen-metal bonds
+6.6.1	Forming coordination complexes
+1.1.1.1	Alcohol dehydrogenase
+1.1.1.2	Alcohol dehydrogenase (NADP(+))
+1.1.1.3	Homoserine dehydrogenase
+1.1.1.4	(R,R)-butanediol dehydrogenase
+1.1.1.5	Transferred entry: 1.1.1.303 and 1.1.1.304
+1.1.1.6	Glycerol dehydrogenase
+1.1.1.7	Propanediol-phosphate dehydrogenase
+1.1.1.8	Glycerol-3-phosphate dehydrogenase (NAD(+))
+1.1.1.9	D-xylulose reductase
+1.1.1.10	L-xylulose reductase
+1.1.1.11	D-arabinitol 4-dehydrogenase
+1.1.1.12	L-arabinitol 4-dehydrogenase
+1.1.1.13	L-arabinitol 2-dehydrogenase
+1.1.1.14	L-iditol 2-dehydrogenase
+1.1.1.15	D-iditol 2-dehydrogenase
+1.1.1.16	Galactitol 2-dehydrogenase
+1.1.1.17	Mannitol-1-phosphate 5-dehydrogenase
+1.1.1.18	Inositol 2-dehydrogenase
+1.1.1.19	Glucuronate reductase
+1.1.1.20	Glucuronolactone reductase
+1.1.1.21	Aldehyde reductase
+1.1.1.22	UDP-glucose 6-dehydrogenase
+1.1.1.23	Histidinol dehydrogenase
+1.1.1.24	Quinate dehydrogenase
+1.1.1.25	Shikimate dehydrogenase
+1.1.1.26	Glyoxylate reductase
+1.1.1.27	L-lactate dehydrogenase
+1.1.1.28	D-lactate dehydrogenase
+1.1.1.29	Glycerate dehydrogenase
+1.1.1.30	3-hydroxybutyrate dehydrogenase
+1.1.1.31	3-hydroxyisobutyrate dehydrogenase
+1.1.1.32	Mevaldate reductase
+1.1.1.33	Mevaldate reductase (NADPH)
+1.1.1.34	Hydroxymethylglutaryl-CoA reductase (NADPH)
+1.1.1.35	3-hydroxyacyl-CoA dehydrogenase
+1.1.1.36	Acetoacetyl-CoA reductase
+1.1.1.37	Malate dehydrogenase
+1.1.1.38	Malate dehydrogenase (oxaloacetate-decarboxylating)
+1.1.1.39	Malate dehydrogenase (decarboxylating)
+1.1.1.40	Malate dehydrogenase (oxaloacetate-decarboxylating) (NADP(+))
+1.1.1.41	Isocitrate dehydrogenase (NAD(+))
+1.1.1.42	Isocitrate dehydrogenase (NADP(+))
+1.1.1.43	Phosphogluconate 2-dehydrogenase
+1.1.1.44	Phosphogluconate dehydrogenase (NADP(+)-dependent, decarboxylating)
+1.1.1.45	L-gulonate 3-dehydrogenase
+1.1.1.46	L-arabinose 1-dehydrogenase
+1.1.1.47	Glucose 1-dehydrogenase (NAD(P)(+))
+1.1.1.48	D-galactose 1-dehydrogenase
+1.1.1.49	Glucose-6-phosphate dehydrogenase (NADP(+))
+1.1.1.50	3-alpha-hydroxysteroid 3-dehydrogenase (Si-specific)
+1.1.1.51	3(or 17)-beta-hydroxysteroid dehydrogenase
+1.1.1.52	3-alpha-hydroxycholanate dehydrogenase (NAD(+))
+1.1.1.53	3-alpha(or 20-beta)-hydroxysteroid dehydrogenase
+1.1.1.54	Allyl-alcohol dehydrogenase
+1.1.1.55	Lactaldehyde reductase (NADPH)
+1.1.1.56	Ribitol 2-dehydrogenase
+1.1.1.57	Fructuronate reductase
+1.1.1.58	Tagaturonate reductase
+1.1.1.59	3-hydroxypropionate dehydrogenase
+1.1.1.60	2-hydroxy-3-oxopropionate reductase
+1.1.1.61	4-hydroxybutyrate dehydrogenase
+1.1.1.62	17-beta-estradiol 17-dehydrogenase
+1.1.1.63	Transferred entry: 1.1.1.239
+1.1.1.64	Testosterone 17-beta-dehydrogenase (NADP(+))
+1.1.1.65	Pyridoxine 4-dehydrogenase
+1.1.1.66	Omega-hydroxydecanoate dehydrogenase
+1.1.1.67	Mannitol 2-dehydrogenase
+1.1.1.68	Transferred entry: 1.5.1.20
+1.1.1.69	Gluconate 5-dehydrogenase
+1.1.1.70	Transferred entry: 1.2.1.3
+1.1.1.71	Alcohol dehydrogenase (NAD(P)(+))
+1.1.1.72	Glycerol dehydrogenase (NADP(+))
+1.1.1.73	Octanol dehydrogenase
+1.1.1.74	Deleted entry
+1.1.1.75	(R)-aminopropanol dehydrogenase
+1.1.1.76	(S,S)-butanediol dehydrogenase
+1.1.1.77	Lactaldehyde reductase
+1.1.1.78	Methylglyoxal reductase (NADH)
+1.1.1.79	Glyoxylate reductase (NADP(+))
+1.1.1.80	Isopropanol dehydrogenase (NADP(+))
+1.1.1.81	Hydroxypyruvate reductase
+1.1.1.82	Malate dehydrogenase (NADP(+))
+1.1.1.83	D-malate dehydrogenase (decarboxylating)
+1.1.1.84	Dimethylmalate dehydrogenase
+1.1.1.85	3-isopropylmalate dehydrogenase
+1.1.1.86	Ketol-acid reductoisomerase (NADP(+))
+1.1.1.87	Homoisocitrate dehydrogenase
+1.1.1.88	Hydroxymethylglutaryl-CoA reductase
+1.1.1.89	Transferred entry: 1.1.1.86
+1.1.1.90	Aryl-alcohol dehydrogenase
+1.1.1.91	Aryl-alcohol dehydrogenase (NADP(+))
+1.1.1.92	Oxaloglycolate reductase (decarboxylating)
+1.1.1.93	Tartrate dehydrogenase
+1.1.1.94	Glycerol-3-phosphate dehydrogenase (NAD(P)(+))
+1.1.1.95	Phosphoglycerate dehydrogenase
+1.1.1.96	Diiodophenylpyruvate reductase
+1.1.1.97	3-hydroxybenzyl-alcohol dehydrogenase
+1.1.1.98	(R)-2-hydroxy-fatty-acid dehydrogenase
+1.1.1.99	(S)-2-hydroxy-fatty-acid dehydrogenase
+1.1.1.100	3-oxoacyl-[acyl-carrier-protein] reductase
+1.1.1.101	Acylglycerone-phosphate reductase
+1.1.1.102	3-dehydrosphinganine reductase
+1.1.1.103	L-threonine 3-dehydrogenase
+1.1.1.104	4-oxoproline reductase
+1.1.1.105	All-trans-retinol dehydrogenase (NAD(+))
+1.1.1.106	Pantoate 4-dehydrogenase
+1.1.1.107	Pyridoxal 4-dehydrogenase
+1.1.1.108	Carnitine 3-dehydrogenase
+1.1.1.109	Transferred entry: 1.3.1.28
+1.1.1.110	Indolelactate dehydrogenase
+1.1.1.111	3-(imidazol-5-yl)lactate dehydrogenase
+1.1.1.112	Indanol dehydrogenase
+1.1.1.113	L-xylose 1-dehydrogenase
+1.1.1.114	Apiose 1-reductase
+1.1.1.115	Ribose 1-dehydrogenase (NADP(+))
+1.1.1.116	D-arabinose 1-dehydrogenase (NAD(+))
+1.1.1.117	D-arabinose 1-dehydrogenase (NAD(P)(+))
+1.1.1.118	Glucose 1-dehydrogenase (NAD(+))
+1.1.1.119	Glucose 1-dehydrogenase (NADP(+))
+1.1.1.120	Galactose 1-dehydrogenase (NADP(+))
+1.1.1.121	Aldose 1-dehydrogenase (NAD(+))
+1.1.1.122	D-threo-aldose 1-dehydrogenase
+1.1.1.123	Sorbose 5-dehydrogenase (NADP(+))
+1.1.1.124	Fructose 5-dehydrogenase (NADP(+))
+1.1.1.125	2-deoxy-D-gluconate 3-dehydrogenase
+1.1.1.126	2-dehydro-3-deoxy-D-gluconate 6-dehydrogenase
+1.1.1.127	2-dehydro-3-deoxy-D-gluconate 5-dehydrogenase
+1.1.1.128	Deleted entry
+1.1.1.129	L-threonate 3-dehydrogenase
+1.1.1.130	3-dehydro-L-gulonate 2-dehydrogenase
+1.1.1.131	Mannuronate reductase
+1.1.1.132	GDP-mannose 6-dehydrogenase
+1.1.1.133	dTDP-4-dehydrorhamnose reductase
+1.1.1.134	dTDP-6-deoxy-L-talose 4-dehydrogenase
+1.1.1.135	GDP-6-deoxy-D-talose 4-dehydrogenase
+1.1.1.136	UDP-N-acetylglucosamine 6-dehydrogenase
+1.1.1.137	Ribitol-5-phosphate 2-dehydrogenase
+1.1.1.138	Mannitol 2-dehydrogenase (NADP(+))
+1.1.1.139	Transferred entry: 1.1.1.21
+1.1.1.140	Sorbitol-6-phosphate 2-dehydrogenase
+1.1.1.141	15-hydroxyprostaglandin dehydrogenase (NAD(+))
+1.1.1.142	D-pinitol dehydrogenase
+1.1.1.143	Sequoyitol dehydrogenase
+1.1.1.144	Perillyl-alcohol dehydrogenase
+1.1.1.145	3-beta-hydroxy-Delta(5)-steroid dehydrogenase
+1.1.1.146	11-beta-hydroxysteroid dehydrogenase
+1.1.1.147	16-alpha-hydroxysteroid dehydrogenase
+1.1.1.148	Estradiol 17-alpha-dehydrogenase
+1.1.1.149	20-alpha-hydroxysteroid dehydrogenase
+1.1.1.150	21-hydroxysteroid dehydrogenase (NAD(+))
+1.1.1.151	21-hydroxysteroid dehydrogenase (NADP(+))
+1.1.1.152	3-alpha-hydroxy-5-beta-androstane-17-one 3-alpha-dehydrogenase
+1.1.1.153	Sepiapterin reductase (L-erythro-7,8-dihydrobiopterin forming)
+1.1.1.154	Ureidoglycolate dehydrogenase
+1.1.1.155	Transferred entry: 1.1.1.87
+1.1.1.156	Glycerol 2-dehydrogenase (NADP(+))
+1.1.1.157	3-hydroxybutyryl-CoA dehydrogenase
+1.1.1.158	Transferred entry: 1.3.1.98
+1.1.1.159	7-alpha-hydroxysteroid dehydrogenase
+1.1.1.160	Dihydrobunolol dehydrogenase
+1.1.1.161	Deleted entry
+1.1.1.162	Erythrulose reductase
+1.1.1.163	Cyclopentanol dehydrogenase
+1.1.1.164	Hexadecanol dehydrogenase
+1.1.1.165	2-alkyn-1-ol dehydrogenase
+1.1.1.166	Hydroxycyclohexanecarboxylate dehydrogenase
+1.1.1.167	Hydroxymalonate dehydrogenase
+1.1.1.168	2-dehydropantolactone reductase (Re-specific)
+1.1.1.169	2-dehydropantoate 2-reductase
+1.1.1.170	(decarboxylating)
+1.1.1.171	Transferred entry: 1.5.1.20
+1.1.1.172	2-oxoadipate reductase
+1.1.1.173	L-rhamnose 1-dehydrogenase
+1.1.1.174	Cyclohexane-1,2-diol dehydrogenase
+1.1.1.175	D-xylose 1-dehydrogenase
+1.1.1.176	12-alpha-hydroxysteroid dehydrogenase
+1.1.1.177	Glycerol-3-phosphate 1-dehydrogenase (NADP(+))
+1.1.1.178	3-hydroxy-2-methylbutyryl-CoA dehydrogenase
+1.1.1.179	D-xylose 1-dehydrogenase (NADP(+))
+1.1.1.180	Transferred entry: 1.1.1.131
+1.1.1.181	Cholest-5-ene-3-beta,7-alpha-diol 3-beta-dehydrogenase
+1.1.1.182	Transferred entry: 1.1.1.198, 1.1.1.227 and 1.1.1.228
+1.1.1.183	Geraniol dehydrogenase (NADP(+))
+1.1.1.184	Carbonyl reductase (NADPH)
+1.1.1.185	L-glycol dehydrogenase
+1.1.1.186	dTDP-galactose 6-dehydrogenase
+1.1.1.187	GDP-4-dehydro-D-rhamnose reductase
+1.1.1.188	Prostaglandin-F synthase
+1.1.1.189	Prostaglandin-E(2) 9-reductase
+1.1.1.190	Indole-3-acetaldehyde reductase (NADH)
+1.1.1.191	Indole-3-acetaldehyde reductase (NADPH)
+1.1.1.192	Long-chain-alcohol dehydrogenase
+1.1.1.193	5-amino-6-(5-phosphoribosylamino)uracil reductase
+1.1.1.194	Coniferyl-alcohol dehydrogenase
+1.1.1.195	Cinnamyl-alcohol dehydrogenase
+1.1.1.196	15-hydroxyprostaglandin-D dehydrogenase (NADP(+))
+1.1.1.197	15-hydroxyprostaglandin dehydrogenase (NADP(+))
+1.1.1.198	(+)-borneol dehydrogenase
+1.1.1.199	(S)-usnate reductase
+1.1.1.200	Aldose-6-phosphate reductase (NADPH)
+1.1.1.201	7-beta-hydroxysteroid dehydrogenase (NADP(+))
+1.1.1.202	1,3-propanediol dehydrogenase
+1.1.1.203	Uronate dehydrogenase
+1.1.1.204	Transferred entry: 1.17.1.4
+1.1.1.205	IMP dehydrogenase
+1.1.1.206	Tropinone reductase I
+1.1.1.207	(-)-menthol dehydrogenase
+1.1.1.208	(+)-neomenthol dehydrogenase
+1.1.1.209	3(or 17)-alpha-hydroxysteroid dehydrogenase
+1.1.1.210	3-beta-(or 20-alpha)-hydroxysteroid dehydrogenase
+1.1.1.211	Long-chain-3-hydroxyacyl-CoA dehydrogenase
+1.1.1.212	3-oxoacyl-[acyl-carrier-protein] reductase (NADH)
+1.1.1.213	3-alpha-hydroxysteroid dehydrogenase (Re-specific)
+1.1.1.214	2-dehydropantolactone reductase (Si-specific)
+1.1.1.215	Gluconate 2-dehydrogenase
+1.1.1.216	Farnesol dehydrogenase
+1.1.1.217	Benzyl-2-methyl-hydroxybutyrate dehydrogenase
+1.1.1.218	Morphine 6-dehydrogenase
+1.1.1.219	Dihydrokaempferol 4-reductase
+1.1.1.220	6-pyruvoyltetrahydropterin 2'-reductase
+1.1.1.221	Vomifoliol dehydrogenase
+1.1.1.222	(R)-4-hydroxyphenyllactate dehydrogenase
+1.1.1.223	Isopiperitenol dehydrogenase
+1.1.1.224	Mannose-6-phosphate 6-reductase
+1.1.1.225	Chlordecone reductase
+1.1.1.226	4-hydroxycyclohexanecarboxylate dehydrogenase
+1.1.1.227	(-)-borneol dehydrogenase
+1.1.1.228	(+)-sabinol dehydrogenase
+1.1.1.229	Diethyl 2-methyl-3-oxosuccinate reductase
+1.1.1.230	3-alpha-hydroxyglycyrrhetinate dehydrogenase
+1.1.1.231	15-hydroxyprostaglandin-I dehydrogenase (NADP(+))
+1.1.1.232	15-hydroxyicosatetraenoate dehydrogenase
+1.1.1.233	N-acylmannosamine 1-dehydrogenase
+1.1.1.234	Flavanone 4-reductase
+1.1.1.235	8-oxocoformycin reductase
+1.1.1.236	Tropinone reductase II
+1.1.1.237	Hydroxyphenylpyruvate reductase
+1.1.1.238	12-beta-hydroxysteroid dehydrogenase
+1.1.1.239	3-alpha-(17-beta)-hydroxysteroid dehydrogenase (NAD(+))
+1.1.1.240	N-acetylhexosamine 1-dehydrogenase
+1.1.1.241	6-endo-hydroxycineole dehydrogenase
+1.1.1.242	Transferred entry: 1.3.1.69
+1.1.1.243	Carveol dehydrogenase
+1.1.1.244	Methanol dehydrogenase
+1.1.1.245	Cyclohexanol dehydrogenase
+1.1.1.246	Transferred entry: 1.1.1.348 and 4.2.1.139
+1.1.1.247	Codeinone reductase (NADPH)
+1.1.1.248	Salutaridine reductase (NADPH)
+1.1.1.249	Transferred entry: 2.5.1.46
+1.1.1.250	D-arabinitol 2-dehydrogenase
+1.1.1.251	Galactitol-1-phosphate 5-dehydrogenase
+1.1.1.252	Tetrahydroxynaphthalene reductase
+1.1.1.253	Transferred entry: 1.5.1.33
+1.1.1.254	(S)-carnitine 3-dehydrogenase
+1.1.1.255	Mannitol dehydrogenase
+1.1.1.256	Fluoren-9-ol dehydrogenase
+1.1.1.257	4-(hydroxymethyl)benzenesulfonate dehydrogenase
+1.1.1.258	6-hydroxyhexanoate dehydrogenase
+1.1.1.259	3-hydroxypimeloyl-CoA dehydrogenase
+1.1.1.260	Sulcatone reductase
+1.1.1.261	sn-glycerol-1-phosphate dehydrogenase
+1.1.1.262	4-hydroxythreonine-4-phosphate dehydrogenase
+1.1.1.263	1,5-anhydro-D-fructose reductase
+1.1.1.264	L-idonate 5-dehydrogenase (NAD(P)(+))
+1.1.1.265	3-methylbutanal reductase
+1.1.1.266	dTDP-4-dehydro-6-deoxyglucose reductase
+1.1.1.267	1-deoxy-D-xylulose-5-phosphate reductoisomerase
+1.1.1.268	2-(R)-hydroxypropyl-CoM dehydrogenase
+1.1.1.269	2-(S)-hydroxypropyl-CoM dehydrogenase
+1.1.1.270	3-beta-hydroxysteroid 3-dehydrogenase
+1.1.1.271	GDP-L-fucose synthase
+1.1.1.272	D-2-hydroxyacid dehydrogenase (NADP(+))
+1.1.1.273	Vellosimine dehydrogenase
+1.1.1.274	2,5-didehydrogluconate reductase (2-dehydro-D-gluconate-forming)
+1.1.1.275	(+)-trans-carveol dehydrogenase
+1.1.1.276	Serine 3-dehydrogenase (NADP(+))
+1.1.1.277	3-beta-hydroxy-5-beta-steroid dehydrogenase
+1.1.1.278	3-beta-hydroxy-5-alpha-steroid dehydrogenase
+1.1.1.279	(R)-3-hydroxyacid-ester dehydrogenase
+1.1.1.280	(S)-3-hydroxyacid-ester dehydrogenase
+1.1.1.281	GDP-4-dehydro-6-deoxy-D-mannose reductase
+1.1.1.282	Quinate/shikimate dehydrogenase
+1.1.1.283	Methylglyoxal reductase (NADPH)
+1.1.1.284	S-(hydroxymethyl)glutathione dehydrogenase
+1.1.1.285	3''-deamino-3''-oxonicotianamine reductase
+1.1.1.286	Isocitrate--homoisocitrate dehydrogenase
+1.1.1.287	D-arabinitol dehydrogenase (NADP(+))
+1.1.1.288	Xanthoxin dehydrogenase
+1.1.1.289	Sorbose reductase
+1.1.1.290	4-phosphoerythronate dehydrogenase
+1.1.1.291	2-hydroxymethylglutarate dehydrogenase
+1.1.1.292	1,5-anhydro-D-fructose reductase (1,5-anhydro-D-mannitol-forming)
+1.1.1.293	Deleted entry
+1.1.1.294	Chlorophyll(ide) b reductase
+1.1.1.295	Momilactone-A synthase
+1.1.1.296	Dihydrocarveol dehydrogenase
+1.1.1.297	Limonene-1,2-diol dehydrogenase
+1.1.1.298	3-hydroxypropionate dehydrogenase (NADP(+))
+1.1.1.299	Malate dehydrogenase (NAD(P)(+))
+1.1.1.300	NADP-retinol dehydrogenase
+1.1.1.301	D-arabitol-phosphate dehydrogenase
+1.1.1.302	2,5-diamino-6-(ribosylamino)-4(3H)-pyrimidinone 5'-phosphate reductase
+1.1.1.303	Diacetyl reductase ((R)-acetoin forming)
+1.1.1.304	Diacetyl reductase ((S)-acetoin forming)
+1.1.1.305	UDP-glucuronic acid oxidase (UDP-4-keto-hexauronic acid decarboxylating)
+1.1.1.306	S-(hydroxymethyl)mycothiol dehydrogenase
+1.1.1.307	D-xylose reductase
+1.1.1.308	Sulfopropanediol 3-dehydrogenase
+1.1.1.309	Phosphonoacetaldehyde reductase (NADH)
+1.1.1.310	(S)-sulfolactate dehydrogenase
+1.1.1.311	(S)-1-phenylethanol dehydrogenase
+1.1.1.312	2-hydroxy-4-carboxymuconate semialdehyde hemiacetal dehydrogenase
+1.1.1.313	Sulfoacetaldehyde reductase
+1.1.1.314	Germacrene A alcohol dehydrogenase
+1.1.1.315	11-cis-retinol dehydrogenase
+1.1.1.316	L-galactose 1-dehydrogenase
+1.1.1.317	Perakine reductase
+1.1.1.318	Eugenol synthase
+1.1.1.319	Isoeugenol synthase
+1.1.1.320	Benzil reductase ((S)-benzoin forming)
+1.1.1.321	Benzil reductase ((R)-benzoin forming)
+1.1.1.322	(-)-endo-fenchol dehydrogenase
+1.1.1.323	(+)-thujan-3-ol dehydrogenase
+1.1.1.324	8-hydroxygeraniol dehydrogenase
+1.1.1.325	Sepiapterin reductase (L-threo-7,8-dihydrobiopterin forming)
+1.1.1.326	Zerumbone synthase
+1.1.1.327	5-exo-hydroxycamphor dehydrogenase
+1.1.1.328	Nicotine blue oxidoreductase
+1.1.1.329	2-deoxy-scyllo-inosamine dehydrogenase
+1.1.1.330	Very-long-chain 3-oxoacyl-CoA reductase
+1.1.1.331	Secoisolariciresinol dehydrogenase
+1.1.1.332	Chanoclavine-I dehydrogenase
+1.1.1.333	Decaprenylphospho-beta-D-erythro-pentofuranosid-2-ulose 2-reductase
+1.1.1.334	Methylecgonone reductase
+1.1.1.335	UDP-N-acetyl-2-amino-2-deoxyglucuronate dehydrogenase
+1.1.1.336	UDP-N-acetyl-D-mannosamine dehydrogenase
+1.1.1.337	L-2-hydroxycarboxylate dehydrogenase (NAD(+))
+1.1.1.338	(2R)-3-sulfolactate dehydrogenase (NADP(+))
+1.1.1.339	dTDP-6-deoxy-L-talose 4-dehydrogenase (NAD(+))
+1.1.1.340	1-deoxy-11-beta-hydroxypentalenate dehydrogenase
+1.1.1.341	CDP-abequose synthase
+1.1.1.342	CDP-paratose synthase
+1.1.1.343	Phosphogluconate dehydrogenase (NAD(+)-dependent, decarboxylating)
+1.1.1.344	dTDP-6-deoxy-L-talose 4-dehydrogenase (NAD(P)(+))
+1.1.1.345	D-2-hydroxyacid dehydrogenase (NAD(+))
+1.1.1.346	2,5-didehydrogluconate reductase (2-dehydro-L-gulonate-forming)
+1.1.1.347	Geraniol dehydrogenase (NAD(+))
+1.1.1.348	Vestitone reductase
+1.1.1.349	Norsolorinic acid ketoreductase
+1.1.1.350	Ureidoglycolate dehydrogenase (NAD(+))
+1.1.1.351	Phosphogluconate dehydrogenase (NAD(P)(+)-dependent, decarboxylating)
+1.1.1.352	5'-hydroxyaverantin dehydrogenase
+1.1.1.353	Versiconal hemiacetal acetate reductase
+1.1.1.354	Farnesol dehydrogenase (NAD(+))
+1.1.1.355	2'-dehydrokanamycin reductase
+1.1.1.356	GDP-L-colitose synthase
+1.1.1.357	3-alpha-hydroxysteroid 3-dehydrogenase
+1.1.1.358	2-dehydropantolactone reductase
+1.1.1.359	Aldose 1-dehydrogenase (NAD(P)(+))
+1.1.1.360	Glucose/galactose 1-dehydrogenase
+1.1.1.361	Glucose-6-phosphate 3-dehydrogenase
+1.1.1.362	Aklaviketone reductase
+1.1.1.363	Glucose-6-phosphate dehydrogenase (NAD(P)(+))
+1.1.1.364	dTDP-4-dehydro-6-deoxy-alpha-D-gulose 4-ketoreductase
+1.1.1.365	D-galacturonate reductase
+1.1.1.366	L-idonate 5-dehydrogenase (NAD(+))
+1.1.1.367	UDP-2-acetamido-2,6-beta-L-arabino-hexul-4-ose reductase
+1.1.1.368	6-hydroxycyclohex-1-ene-1-carbonyl-CoA dehydrogenase
+1.1.1.369	D-chiro-inositol 1-dehydrogenase
+1.1.1.370	Scyllo-inositol 2-dehydrogenase (NAD(+))
+1.1.1.371	Scyllo-inositol 2-dehydrogenase (NADP(+))
+1.1.1.372	D/L-glyceraldehyde reductase
+1.1.1.373	Sulfolactaldehyde 3-reductase
+1.1.1.374	UDP-N-acetylglucosamine 3-dehydrogenase
+1.1.1.375	L-2-hydroxycarboxylate dehydrogenase (NAD(P)(+))
+1.1.1.376	L-arabinose 1-dehydrogenase (NAD(P)(+))
+1.1.1.377	L-rhamnose 1-dehydrogenase (NADP(+))
+1.1.1.378	L-rhamnose 1-dehydrogenase (NAD(P)(+))
+1.1.1.379	(R)-mandelate dehydrogenase
+1.1.1.380	L-gulonate 5-dehydrogenase
+1.1.1.381	3-hydroxy acid dehydrogenase
+1.1.1.382	Ketol-acid reductoisomerase (NAD(+))
+1.1.1.383	Ketol-acid reductoisomerase (NAD(P)(+))
+1.1.1.384	dTDP-3,4-didehydro-2,6-dideoxy-alpha-D-glucose 3-reductase
+1.1.1.385	Dihydroanticapsin 7-dehydrogenase
+1.1.1.386	Ipsdienol dehydrogenase
+1.1.1.387	L-serine 3-dehydrogenase (NAD(+))
+1.1.1.388	Glucose-6-phosphate dehydrogenase (NAD(+))
+1.1.1.389	2-dehydro-3-deoxy-L-galactonate 5-dehydrogenase
+1.1.1.390	Sulfoquinovose 1-dehydrogenase
+1.1.2.1	Transferred entry: 1.1.5.3
+1.1.2.2	Mannitol dehydrogenase (cytochrome)
+1.1.2.3	L-lactate dehydrogenase (cytochrome)
+1.1.2.4	D-lactate dehydrogenase (cytochrome)
+1.1.2.5	D-lactate dehydrogenase (cytochrome c-553)
+1.1.2.6	Polyvinyl alcohol dehydrogenase (cytochrome)
+1.1.2.7	Methanol dehydrogenase (cytochrome c)
+1.1.2.8	Alcohol dehydrogenase (cytochrome c)
+1.1.3.1	Transferred entry: 1.1.3.15
+1.1.3.2	Transferred entry: 1.13.12.4
+1.1.3.3	Deleted entry
+1.1.3.4	Glucose oxidase
+1.1.3.5	Hexose oxidase
+1.1.3.6	Cholesterol oxidase
+1.1.3.7	Aryl-alcohol oxidase
+1.1.3.8	L-gulonolactone oxidase
+1.1.3.9	Galactose oxidase
+1.1.3.10	Pyranose oxidase
+1.1.3.11	L-sorbose oxidase
+1.1.3.12	Pyridoxine 4-oxidase
+1.1.3.13	Alcohol oxidase
+1.1.3.14	Catechol oxidase (dimerizing)
+1.1.3.15	(S)-2-hydroxy-acid oxidase
+1.1.3.16	Ecdysone oxidase
+1.1.3.17	Choline oxidase
+1.1.3.18	Secondary-alcohol oxidase
+1.1.3.19	4-hydroxymandelate oxidase (decarboxylating)
+1.1.3.20	Long-chain-alcohol oxidase
+1.1.3.21	Glycerol-3-phosphate oxidase
+1.1.3.22	Transferred entry: 1.17.3.2
+1.1.3.23	Thiamine oxidase
+1.1.3.24	Transferred entry: 1.3.3.12
+1.1.3.25	Transferred entry: 1.1.99.18
+1.1.3.26	Transferred entry: 1.21.3.2
+1.1.3.27	Hydroxyphytanate oxidase
+1.1.3.28	Nucleoside oxidase
+1.1.3.29	N-acylhexosamine oxidase
+1.1.3.30	Polyvinyl-alcohol oxidase
+1.1.3.31	Deleted entry
+1.1.3.32	Transferred entry: 1.14.21.1
+1.1.3.33	Transferred entry: 1.14.21.2
+1.1.3.34	Transferred entry: 1.14.21.3
+1.1.3.35	Transferred entry: 1.14.21.4
+1.1.3.36	Transferred entry: 1.14.21.5
+1.1.3.37	D-arabinono-1,4-lactone oxidase
+1.1.3.38	Vanillyl-alcohol oxidase
+1.1.3.39	Nucleoside oxidase (H(2)O(2)-forming)
+1.1.3.40	D-mannitol oxidase
+1.1.3.41	Alditol oxidase
+1.1.3.42	Prosolanapyrone-II oxidase
+1.1.3.43	Paromamine 6'-oxidase
+1.1.3.44	6'''-hydroxyneomycin C oxidase
+1.1.3.45	Aclacinomycin-N oxidase
+1.1.3.46	4-hydroxymandelate oxidase
+1.1.3.47	5-(hydroxymethyl)furfural oxidase
+1.1.3.48	3-deoxy-alpha-D-manno-octulosonate 8-oxidase
+1.1.4.1	Transferred entry: 1.17.4.4
+1.1.4.2	Transferred entry: 1.17.4.5
+1.1.5.1	Deleted entry
+1.1.5.2	Quinoprotein glucose dehydrogenase (PQQ, quinone)
+1.1.5.3	Glycerol-3-phosphate dehydrogenase
+1.1.5.4	Malate dehydrogenase (quinone)
+1.1.5.5	Alcohol dehydrogenase (quinone)
+1.1.5.6	Formate dehydrogenase-N
+1.1.5.7	Cyclic alcohol dehydrogenase (quinone)
+1.1.5.8	Quinate dehydrogenase (quinone)
+1.1.5.9	Glucose 1-dehydrogenase (FAD, quinone)
+1.1.5.10	D-2-hydroxyacid dehydrogenase (quinone)
+1.1.9.1	Alcohol dehydrogenase (azurin)
+1.1.98.1	Transferred entry: 1.1.9.1
+1.1.98.2	Glucose-6-phosphate dehydrogenase (coenzyme-F420)
+1.1.98.3	Decaprenylphospho-beta-D-ribofuranose 2-dehydrogenase
+1.1.98.4	F420H(2):quinone oxidoreductase
+1.1.98.5	Secondary-alcohol dehydrogenase (coenzyme-F420)
+1.1.99.1	Choline dehydrogenase
+1.1.99.2	L-2-hydroxyglutarate dehydrogenase
+1.1.99.3	Gluconate 2-dehydrogenase (acceptor)
+1.1.99.4	Dehydrogluconate dehydrogenase
+1.1.99.5	Transferred entry: 1.1.5.3
+1.1.99.6	D-lactate dehydrogenase (acceptor)
+1.1.99.7	Lactate--malate transhydrogenase
+1.1.99.8	Transferred entry: 1.1.2.7 and 1.1.2.8
+1.1.99.9	Pyridoxine 5-dehydrogenase
+1.1.99.10	Transferred entry: 1.1.5.9
+1.1.99.11	Fructose 5-dehydrogenase
+1.1.99.12	Sorbose dehydrogenase
+1.1.99.13	Glucoside 3-dehydrogenase
+1.1.99.14	Glycolate dehydrogenase
+1.1.99.15	Transferred entry: 1.5.1.20
+1.1.99.16	Transferred entry: 1.1.5.4
+1.1.99.17	Transferred entry: 1.1.5.2
+1.1.99.18	Cellobiose dehydrogenase (acceptor)
+1.1.99.19	Transferred entry: 1.17.99.4
+1.1.99.20	Alkan-1-ol dehydrogenase (acceptor)
+1.1.99.21	D-sorbitol dehydrogenase (acceptor)
+1.1.99.22	Glycerol dehydrogenase (acceptor)
+1.1.99.23	Transferred entry: 1.1.2.6
+1.1.99.24	Hydroxyacid-oxoacid transhydrogenase
+1.1.99.25	Transferred entry: 1.1.5.8
+1.1.99.26	3-hydroxycyclohexanone dehydrogenase
+1.1.99.27	(R)-pantolactone dehydrogenase (flavin)
+1.1.99.28	Glucose-fructose oxidoreductase
+1.1.99.29	Pyranose dehydrogenase (acceptor)
+1.1.99.30	2-oxo-acid reductase
+1.1.99.31	(S)-mandelate dehydrogenase
+1.1.99.32	L-sorbose 1-dehydrogenase
+1.1.99.33	Formate dehydrogenase (acceptor)
+1.1.99.34	Transferred entry: 1.1.98.2
+1.1.99.35	Soluble quinoprotein glucose dehydrogenase
+1.1.99.36	Alcohol dehydrogenase (nicotinoprotein)
+1.1.99.37	Methanol dehydrogenase (nicotinoprotein)
+1.1.99.38	2-deoxy-scyllo-inosamine dehydrogenase (AdoMet-dependent)
+1.1.99.39	D-2-hydroxyglutarate dehydrogenase
+1.2.1.1	Transferred entry: 1.1.1.284 and 4.4.1.22
+1.2.1.2	Formate dehydrogenase
+1.2.1.3	Aldehyde dehydrogenase (NAD(+))
+1.2.1.4	Aldehyde dehydrogenase (NADP(+))
+1.2.1.5	Aldehyde dehydrogenase (NAD(P)(+))
+1.2.1.6	Deleted entry
+1.2.1.7	Benzaldehyde dehydrogenase (NADP(+))
+1.2.1.8	Betaine-aldehyde dehydrogenase
+1.2.1.9	Glyceraldehyde-3-phosphate dehydrogenase (NADP(+))
+1.2.1.10	Acetaldehyde dehydrogenase (acetylating)
+1.2.1.11	Aspartate-semialdehyde dehydrogenase
+1.2.1.12	Glyceraldehyde-3-phosphate dehydrogenase (phosphorylating)
+1.2.1.13	Glyceraldehyde-3-phosphate dehydrogenase (NADP(+)) (phosphorylating)
+1.2.1.14	Transferred entry: 1.1.1.205
+1.2.1.15	Malonate-semialdehyde dehydrogenase
+1.2.1.16	Succinate-semialdehyde dehydrogenase (NAD(P)(+))
+1.2.1.17	Glyoxylate dehydrogenase (acylating)
+1.2.1.18	Malonate-semialdehyde dehydrogenase (acetylating)
+1.2.1.19	Aminobutyraldehyde dehydrogenase
+1.2.1.20	Glutarate-semialdehyde dehydrogenase
+1.2.1.21	Glycolaldehyde dehydrogenase
+1.2.1.22	Lactaldehyde dehydrogenase
+1.2.1.23	2-oxoaldehyde dehydrogenase (NAD(+))
+1.2.1.24	Succinate-semialdehyde dehydrogenase (NAD(+))
+1.2.1.25	2-oxoisovalerate dehydrogenase (acylating)
+1.2.1.26	2,5-dioxovalerate dehydrogenase
+1.2.1.27	Methylmalonate-semialdehyde dehydrogenase (CoA acylating)
+1.2.1.28	Benzaldehyde dehydrogenase (NAD(+))
+1.2.1.29	Aryl-aldehyde dehydrogenase
+1.2.1.30	Aryl-aldehyde dehydrogenase (NADP(+))
+1.2.1.31	L-aminoadipate-semialdehyde dehydrogenase
+1.2.1.32	Aminomuconate-semialdehyde dehydrogenase
+1.2.1.33	(R)-dehydropantoate dehydrogenase
+1.2.1.34	Transferred entry: 1.1.1.131
+1.2.1.35	Transferred entry: 1.1.1.203
+1.2.1.36	Retinal dehydrogenase
+1.2.1.37	Transferred entry: 1.17.1.4
+1.2.1.38	N-acetyl-gamma-glutamyl-phosphate reductase
+1.2.1.39	Phenylacetaldehyde dehydrogenase
+1.2.1.40	Deleted entry
+1.2.1.41	Glutamate-5-semialdehyde dehydrogenase
+1.2.1.42	Hexadecanal dehydrogenase (acylating)
+1.2.1.43	Formate dehydrogenase (NADP(+))
+1.2.1.44	Cinnamoyl-CoA reductase
+1.2.1.45	Transferred entry: 1.1.1.312
+1.2.1.46	Formaldehyde dehydrogenase
+1.2.1.47	4-trimethylammoniobutyraldehyde dehydrogenase
+1.2.1.48	Long-chain-aldehyde dehydrogenase
+1.2.1.49	2-oxoaldehyde dehydrogenase (NADP(+))
+1.2.1.50	Long-chain-fatty-acyl-CoA reductase
+1.2.1.51	Pyruvate dehydrogenase (NADP(+))
+1.2.1.52	Oxoglutarate dehydrogenase (NADP(+))
+1.2.1.53	4-hydroxyphenylacetaldehyde dehydrogenase
+1.2.1.54	Gamma-guanidinobutyraldehyde dehydrogenase
+1.2.1.55	Transferred entry: 1.1.1.279
+1.2.1.56	Transferred entry: 1.1.1.280
+1.2.1.57	Butanal dehydrogenase
+1.2.1.58	Phenylglyoxylate dehydrogenase (acylating)
+1.2.1.59	Glyceraldehyde-3-phosphate dehydrogenase (NAD(P)(+)) (phosphorylating)
+1.2.1.60	5-carboxymethyl-2-hydroxymuconic-semialdehyde dehydrogenase
+1.2.1.61	4-hydroxymuconic-semialdehyde dehydrogenase
+1.2.1.62	4-formylbenzenesulfonate dehydrogenase
+1.2.1.63	6-oxohexanoate dehydrogenase
+1.2.1.64	4-hydroxybenzaldehyde dehydrogenase (NAD(+))
+1.2.1.65	Salicylaldehyde dehydrogenase
+1.2.1.66	Transferred entry: 1.1.1.306
+1.2.1.67	Vanillin dehydrogenase
+1.2.1.68	Coniferyl-aldehyde dehydrogenase
+1.2.1.69	Fluoroacetaldehyde dehydrogenase
+1.2.1.70	Glutamyl-tRNA reductase
+1.2.1.71	Succinylglutamate-semialdehyde dehydrogenase
+1.2.1.72	Erythrose-4-phosphate dehydrogenase
+1.2.1.73	Sulfoacetaldehyde dehydrogenase
+1.2.1.74	Abieta-7,13-dien-18-al dehydrogenase
+1.2.1.75	Malonyl CoA reductase (malonate semialdehyde-forming)
+1.2.1.76	Succinate-semialdehyde dehydrogenase (acetylating)
+1.2.1.77	3,4-dehydroadipyl-CoA semialdehyde dehydrogenase (NADP(+))
+1.2.1.78	2-formylbenzoate dehydrogenase
+1.2.1.79	Succinate-semialdehyde dehydrogenase (NADP(+))
+1.2.1.80	Long-chain acyl-[acyl-carrier-protein] reductase
+1.2.1.81	Sulfoacetaldehyde dehydrogenase (acylating)
+1.2.1.82	Beta-apo-4'-carotenal oxygenase
+1.2.1.83	3-succinoylsemialdehyde-pyridine dehydrogenase
+1.2.1.84	Alcohol-forming fatty acyl-CoA reductase
+1.2.1.85	2-hydroxymuconate-6-semialdehyde dehydrogenase
+1.2.1.86	Geranial dehydrogenase
+1.2.1.87	Propanal dehydrogenase (CoA-propanoylating)
+1.2.1.88	L-glutamate gamma-semialdehyde dehydrogenase
+1.2.1.89	D-glyceraldehyde dehydrogenase (NADP(+))
+1.2.1.90	Glyceraldehyde-3-phosphate dehydrogenase (NAD(P)(+))
+1.2.1.91	3-oxo-5,6-dehydrosuberyl-CoA semialdehyde dehydrogenase
+1.2.1.92	3,6-anhydro-alpha-L-galactose dehydrogenase
+1.2.1.93	Formate dehydrogenase (NAD(+), ferredoxin)
+1.2.1.94	Farnesal dehydrogenase
+1.2.1.95	L-2-aminoadipate reductase
+1.2.1.96	4-hydroxybenzaldehyde dehydrogenase (NADP(+))
+1.2.1.97	3-sulfolactaldehyde dehydrogenase
+1.2.2.1	Formate dehydrogenase (cytochrome)
+1.2.2.2	Deleted entry
+1.2.2.3	Formate dehydrogenase (cytochrome c-553)
+1.2.2.4	Carbon-monoxide dehydrogenase (cytochrome b-561)
+1.2.3.1	Aldehyde oxidase
+1.2.3.2	Transferred entry: 1.17.3.2
+1.2.3.3	Pyruvate oxidase
+1.2.3.4	Oxalate oxidase
+1.2.3.5	Glyoxylate oxidase
+1.2.3.6	Pyruvate oxidase (CoA-acetylating)
+1.2.3.7	Indole-3-acetaldehyde oxidase
+1.2.3.8	Pyridoxal oxidase
+1.2.3.9	Aryl-aldehyde oxidase
+1.2.3.10	Deleted entry
+1.2.3.11	Transferred entry: 1.2.3.1
+1.2.3.12	Transferred entry: 1.14.13.82
+1.2.3.13	4-hydroxyphenylpyruvate oxidase
+1.2.3.14	Abscisic-aldehyde oxidase
+1.2.4.1	Pyruvate dehydrogenase (acetyl-transferring)
+1.2.4.2	Oxoglutarate dehydrogenase (succinyl-transferring)
+1.2.4.3	Transferred entry: 1.2.4.4
+1.2.4.4	3-methyl-2-oxobutanoate dehydrogenase (2-methylpropanoyl-transferring)
+1.2.5.1	Pyruvate dehydrogenase (quinone)
+1.2.5.2	Aldehyde dehydrogenase (quinone)
+1.2.7.1	Pyruvate synthase
+1.2.7.2	Deleted entry
+1.2.7.3	2-oxoglutarate synthase
+1.2.7.4	Carbon-monoxide dehydrogenase (ferredoxin)
+1.2.7.5	Aldehyde ferredoxin oxidoreductase
+1.2.7.6	Glyceraldehyde-3-phosphate dehydrogenase (ferredoxin)
+1.2.7.7	3-methyl-2-oxobutanoate dehydrogenase (ferredoxin)
+1.2.7.8	Indolepyruvate ferredoxin oxidoreductase
+1.2.7.9	Transferred entry: 1.2.7.3
+1.2.7.10	Oxalate oxidoreductase
+1.2.7.11	2-oxoacid oxidoreductase (ferredoxin)
+1.2.98.1	Formaldehyde dismutase
+1.2.99.1	Transferred entry: 1.17.99.4
+1.2.99.2	Carbon-monoxide dehydrogenase (acceptor)
+1.2.99.3	Transferred entry: 1.2.5.2
+1.2.99.4	Transferred entry: 1.2.98.1
+1.2.99.5	Formylmethanofuran dehydrogenase
+1.2.99.6	Carboxylate reductase
+1.2.99.7	Aldehyde dehydrogenase (FAD-independent)
+1.2.99.8	Glyceraldehyde dehydrogenase (FAD-containing)
+1.2.99.9	Formate dehydrogenase (coenzyme F420)
+1.3.1.1	Dihydrouracil dehydrogenase (NAD(+))
+1.3.1.2	Dihydropyrimidine dehydrogenase (NADP(+))
+1.3.1.3	Delta(4)-3-oxosteroid 5-beta-reductase
+1.3.1.4	Transferred entry: 1.3.1.22
+1.3.1.5	Cucurbitacin Delta(23)-reductase
+1.3.1.6	Fumarate reductase (NADH)
+1.3.1.7	Meso-tartrate dehydrogenase
+1.3.1.8	Acyl-CoA dehydrogenase (NADP(+))
+1.3.1.9	Enoyl-[acyl-carrier-protein] reductase (NADH)
+1.3.1.10	Enoyl-[acyl-carrier-protein] reductase (NADPH, Si-specific)
+1.3.1.11	2-coumarate reductase
+1.3.1.12	Prephenate dehydrogenase
+1.3.1.13	Prephenate dehydrogenase (NADP(+))
+1.3.1.14	Dihydroorotate dehydrogenase (NAD(+))
+1.3.1.15	Dihydroorotate dehydrogenase (NADP(+))
+1.3.1.16	Beta-nitroacrylate reductase
+1.3.1.17	3-methyleneoxindole reductase
+1.3.1.18	Kynurenate-7,8-dihydrodiol dehydrogenase
+1.3.1.19	Cis-1,2-dihydrobenzene-1,2-diol dehydrogenase
+1.3.1.20	Trans-1,2-dihydrobenzene-1,2-diol dehydrogenase
+1.3.1.21	7-dehydrocholesterol reductase
+1.3.1.22	3-oxo-5-alpha-steroid 4-dehydrogenase (NADP(+))
+1.3.1.23	Deleted entry
+1.3.1.24	Biliverdin reductase
+1.3.1.25	1,6-dihydroxycyclohexa-2,4-diene-1-carboxylate dehydrogenase
+1.3.1.26	Transferred entry: 1.17.1.8
+1.3.1.27	2-hexadecenal reductase
+1.3.1.28	2,3-dihydro-2,3-dihydroxybenzoate dehydrogenase
+1.3.1.29	Cis-1,2-dihydro-1,2-dihydroxynaphthalene dehydrogenase
+1.3.1.30	Transferred entry: 1.3.1.22
+1.3.1.31	2-enoate reductase
+1.3.1.32	Maleylacetate reductase
+1.3.1.33	Protochlorophyllide reductase
+1.3.1.34	2,4-dienoyl-CoA reductase (NADPH)
+1.3.1.35	Transferred entry: 1.14.19.22
+1.3.1.36	Geissoschizine dehydrogenase
+1.3.1.37	Cis-2-enoyl-CoA reductase (NADPH)
+1.3.1.38	Trans-2-enoyl-CoA reductase (NADPH)
+1.3.1.39	Enoyl-[acyl-carrier-protein] reductase (NADPH, Re-specific)
+1.3.1.40	2-hydroxy-6-oxo-6-phenylhexa-2,4-dienoate reductase
+1.3.1.41	Xanthommatin reductase
+1.3.1.42	12-oxophytodienoate reductase
+1.3.1.43	Arogenate dehydrogenase
+1.3.1.44	Trans-2-enoyl-CoA reductase (NAD(+))
+1.3.1.45	2'-hydroxyisoflavone reductase
+1.3.1.46	Biochanin-A reductase
+1.3.1.47	Alpha-santonin 1,2-reductase
+1.3.1.48	15-oxoprostaglandin 13-reductase
+1.3.1.49	Cis-3,4-dihydrophenanthrene-3,4-diol dehydrogenase
+1.3.1.50	Transferred entry: 1.1.1.252
+1.3.1.51	2'-hydroxydaidzein reductase
+1.3.1.52	Transferred entry: 1.3.8.5
+1.3.1.53	(3S,4R)-3,4-dihydroxycyclohexa-1,5-diene-1,4-dicarboxylate dehydrogenase
+1.3.1.54	Precorrin-6A reductase
+1.3.1.55	Deleted entry
+1.3.1.56	Cis-2,3-dihydrobiphenyl-2,3-diol dehydrogenase
+1.3.1.57	Phloroglucinol reductase
+1.3.1.58	2,3-dihydroxy-2,3-dihydro-p-cumate dehydrogenase
+1.3.1.59	Deleted entry
+1.3.1.60	Dibenzothiophene dihydrodiol dehydrogenase
+1.3.1.61	Deleted entry
+1.3.1.62	Pimeloyl-CoA dehydrogenase
+1.3.1.63	Transferred entry: 1.21.1.2
+1.3.1.64	Phthalate 4,5-cis-dihydrodiol dehydrogenase
+1.3.1.65	5,6-dihydroxy-3-methyl-2-oxo-1,2,5,6-tetrahydroquinoline dehydrogenase
+1.3.1.66	Cis-dihydroethylcatechol dehydrogenase
+1.3.1.67	dehydrogenase
+1.3.1.68	1,2-dihydroxy-6-methylcyclohexa-3,5-dienecarboxylate dehydrogenase
+1.3.1.69	Zeatin reductase
+1.3.1.70	Delta(14)-sterol reductase
+1.3.1.71	Delta(24(24(1)))-sterol reductase
+1.3.1.72	Delta(24)-sterol reductase
+1.3.1.73	1,2-dihydrovomilenine reductase
+1.3.1.74	2-alkenal reductase (NAD(P)(+))
+1.3.1.75	Divinyl chlorophyllide a 8-vinyl-reductase
+1.3.1.76	Precorrin-2 dehydrogenase
+1.3.1.77	Anthocyanidin reductase
+1.3.1.78	Arogenate dehydrogenase (NADP(+))
+1.3.1.79	Arogenate dehydrogenase (NAD(P)(+))
+1.3.1.80	Red chlorophyll catabolite reductase
+1.3.1.81	(+)-pulegone reductase
+1.3.1.82	(-)-isopiperitenone reductase
+1.3.1.83	Geranylgeranyl diphosphate reductase
+1.3.1.84	Acrylyl-CoA reductase (NADPH)
+1.3.1.85	Crotonyl-CoA carboxylase/reductase
+1.3.1.86	Crotonyl-CoA reductase
+1.3.1.87	3-(cis-5,6-dihydroxycyclohexa-1,3-dien-1-yl)propanoate dehydrogenase
+1.3.1.88	tRNA-dihydrouridine(16/17) synthase (NAD(P)(+))
+1.3.1.89	tRNA-dihydrouridine(47) synthase (NAD(P)(+))
+1.3.1.90	tRNA-dihydrouridine(20a/20b) synthase (NAD(P)(+))
+1.3.1.91	tRNA-dihydrouridine(20) synthase (NAD(P)(+))
+1.3.1.92	Artemisinic aldehyde Delta(11(13)) reductase
+1.3.1.93	Very-long-chain enoyl-CoA reductase
+1.3.1.94	Polyprenol reductase
+1.3.1.95	Acryloyl-CoA reductase (NADH)
+1.3.1.96	Botryococcus squalene synthase
+1.3.1.97	Botryococcene synthase
+1.3.1.98	UDP-N-acetylmuramate dehydrogenase
+1.3.1.99	Iridoid synthase
+1.3.1.100	Chanoclavine-I aldehyde reductase
+1.3.1.101	2,3-bis-O-geranylgeranyl-sn-glycerol 1-phosphate reductase (NAD(P)H)
+1.3.1.102	2-alkenal reductase (NADP(+))
+1.3.1.103	2-haloacrylate reductase
+1.3.1.104	Enoyl-[acyl-carrier-protein] reductase
+1.3.1.105	2-methylene-furan-3-one reductase
+1.3.1.106	Cobalt-precorrin-6A reductase
+1.3.1.107	Sanguinarine reductase
+1.3.1.108	Caffeoyl-CoA reductase
+1.3.1.109	Butanoyl-CoA dehydrogenase (NAD(+),ferredoxin)
+1.3.1.110	Lactate dehydrogenase (NAD(+),ferredoxin)
+1.3.2.1	Transferred entry: 1.3.8.1
+1.3.2.2	Transferred entry: 1.3.8.7
+1.3.2.3	L-galactonolactone dehydrogenase
+1.3.3.1	Transferred entry: 1.3.98.1
+1.3.3.2	Transferred entry: 1.14.19.20
+1.3.3.3	Coproporphyrinogen oxidase
+1.3.3.4	Protoporphyrinogen oxidase
+1.3.3.5	Bilirubin oxidase
+1.3.3.6	Acyl-CoA oxidase
+1.3.3.7	Dihydrouracil oxidase
+1.3.3.8	Tetrahydroberberine oxidase
+1.3.3.9	Secologanin synthase
+1.3.3.10	Tryptophan alpha,beta-oxidase
+1.3.3.11	Pyrroloquinoline-quinone synthase
+1.3.3.12	L-galactonolactone oxidase
+1.3.3.13	Albonoursin synthase
+1.3.3.14	Aclacinomycin-A oxidase
+1.3.4.1	Fumarate reductase (CoM/CoB)
+1.3.5.1	Succinate dehydrogenase (quinone)
+1.3.5.2	Dihydroorotate dehydrogenase (quinone)
+1.3.5.3	Protoporphyrinogen IX dehydrogenase (menaquinone)
+1.3.5.4	Fumarate reductase (quinol)
+1.3.5.5	15-cis-phytoene desaturase
+1.3.5.6	9,9'-di-cis-zeta-carotene desaturase
+1.3.7.1	6-hydroxynicotinate reductase
+1.3.7.2	15,16-dihydrobiliverdin:ferredoxin oxidoreductase
+1.3.7.3	Phycoerythrobilin:ferredoxin oxidoreductase
+1.3.7.4	Phytochromobilin:ferredoxin oxidoreductase
+1.3.7.5	Phycocyanobilin:ferredoxin oxidoreductase
+1.3.7.6	Phycoerythrobilin synthase
+1.3.7.7	Ferredoxin:protochlorophyllide reductase (ATP-dependent)
+1.3.7.8	Benzoyl-CoA reductase
+1.3.7.9	4-hydroxybenzoyl-CoA reductase
+1.3.7.10	Transferred entry: 1.14.19.8
+1.3.7.11	2,3-bis-O-geranylgeranyl-sn-glycero-phospholipid reductase
+1.3.8.1	Short-chain acyl-CoA dehydrogenase
+1.3.8.2	4,4'-diapophytoene desaturase (4,4'-diapolycopene-forming)
+1.3.8.3	(R)-benzylsuccinyl-CoA dehydrogenase
+1.3.8.4	Isovaleryl-CoA dehydrogenase
+1.3.8.5	2-methyl-branched-chain-enoyl-CoA reductase
+1.3.8.6	Glutaryl-CoA dehydrogenase (ETF)
+1.3.8.7	Medium-chain acyl-CoA dehydrogenase
+1.3.8.8	Long-chain-acyl-CoA dehydrogenase
+1.3.8.9	Very-long-chain acyl-CoA dehydrogenase
+1.3.8.10	Cyclohex-1-ene-1-carbonyl-CoA dehydrogenase
+1.3.8.11	Cyclohexane-1-carbonyl-CoA dehydrogenase
+1.3.8.12	(2S)-methylsuccinyl-CoA dehydrogenase
+1.3.98.1	Dihydroorotate oxidase (fumarate)
+1.3.98.2	Transferred entry: 1.3.4.1
+1.3.99.1	Deleted entry
+1.3.99.2	Transferred entry: 1.3.8.1
+1.3.99.3	Transferred entry: 1.3.8.7, 1.3.8.8 and 1.3.8.9
+1.3.99.4	3-oxosteroid 1-dehydrogenase
+1.3.99.5	3-oxo-5-alpha-steroid 4-dehydrogenase (acceptor)
+1.3.99.6	3-oxo-5-beta-steroid 4-dehydrogenase
+1.3.99.7	Transferred entry: 1.3.8.6
+1.3.99.8	2-furoyl-CoA dehydrogenase
+1.3.99.9	Transferred entry: 1.21.99.1
+1.3.99.10	Transferred entry: 1.3.8.4
+1.3.99.11	Transferred entry: 1.3.5.2
+1.3.99.12	2-methylacyl-CoA dehydrogenase
+1.3.99.13	Transferred entry: 1.3.8.8
+1.3.99.14	Cyclohexanone dehydrogenase
+1.3.99.15	Transferred entry: 1.3.7.8
+1.3.99.16	Isoquinoline 1-oxidoreductase
+1.3.99.17	Quinoline 2-oxidoreductase
+1.3.99.18	Quinaldate 4-oxidoreductase
+1.3.99.19	Quinoline-4-carboxylate 2-oxidoreductase
+1.3.99.20	Transferred entry: 1.3.7.9
+1.3.99.21	Transferred entry: 1.3.8.3
+1.3.99.22	Coproporphyrinogen dehydrogenase
+1.3.99.23	All-trans-retinol 13,14-reductase
+1.3.99.24	2-amino-4-deoxychorismate dehydrogenase
+1.3.99.25	Carvone reductase
+1.3.99.26	All-trans-zeta-carotene desaturase
+1.3.99.27	1-hydroxycarotenoid 3,4-desaturase
+1.3.99.28	Phytoene desaturase (neurosporene-forming)
+1.3.99.29	Phytoene desaturase (zeta-carotene-forming)
+1.3.99.30	Phytoene desaturase (3,4-didehydrolycopene-forming)
+1.3.99.31	Phytoene desaturase (lycopene-forming)
+1.3.99.32	Glutaryl-CoA dehydrogenase (acceptor)
+1.3.99.33	Urocanate reductase
+1.3.99.34	Transferred entry: 1.3.7.11
+1.3.99.35	Chlorophyllide a reductase
+1.3.99.36	Cypemycin cysteine dehydrogenase (decarboxylating)
+1.3.99.37	1-hydroxy-2-isopentenylcarotenoid 3,4-desaturase
+1.4.1.1	Alanine dehydrogenase
+1.4.1.2	Glutamate dehydrogenase
+1.4.1.3	Glutamate dehydrogenase (NAD(P)(+))
+1.4.1.4	Glutamate dehydrogenase (NADP(+))
+1.4.1.5	L-amino-acid dehydrogenase
+1.4.1.6	Transferred entry: 1.21.4.1
+1.4.1.7	Serine 2-dehydrogenase
+1.4.1.8	Valine dehydrogenase (NADP(+))
+1.4.1.9	Leucine dehydrogenase
+1.4.1.10	Glycine dehydrogenase
+1.4.1.11	L-erythro-3,5-diaminohexanoate dehydrogenase
+1.4.1.12	2,4-diaminopentanoate dehydrogenase
+1.4.1.13	Glutamate synthase (NADPH)
+1.4.1.14	Glutamate synthase (NADH)
+1.4.1.15	Lysine dehydrogenase
+1.4.1.16	Diaminopimelate dehydrogenase
+1.4.1.17	N-methylalanine dehydrogenase
+1.4.1.18	Lysine 6-dehydrogenase
+1.4.1.19	Tryptophan dehydrogenase
+1.4.1.20	Phenylalanine dehydrogenase
+1.4.1.21	Aspartate dehydrogenase
+1.4.1.23	Valine dehydrogenase (NAD(+))
+1.4.1.24	3-dehydroquinate synthase II
+1.4.2.1	Glycine dehydrogenase (cytochrome)
+1.4.3.1	D-aspartate oxidase
+1.4.3.2	L-amino-acid oxidase
+1.4.3.3	D-amino-acid oxidase
+1.4.3.4	Monoamine oxidase
+1.4.3.5	Pyridoxal 5'-phosphate synthase
+1.4.3.6	Transferred entry: 1.4.3.21 and 1.4.3.22
+1.4.3.7	D-glutamate oxidase
+1.4.3.8	Ethanolamine oxidase
+1.4.3.9	Transferred entry: 1.4.3.4
+1.4.3.10	Putrescine oxidase
+1.4.3.11	L-glutamate oxidase
+1.4.3.12	Cyclohexylamine oxidase
+1.4.3.13	Protein-lysine 6-oxidase
+1.4.3.14	L-lysine oxidase
+1.4.3.15	D-glutamate(D-aspartate) oxidase
+1.4.3.16	L-aspartate oxidase
+1.4.3.17	Transferred entry: 1.3.3.10
+1.4.3.18	Deleted entry
+1.4.3.19	Glycine oxidase
+1.4.3.20	L-lysine 6-oxidase
+1.4.3.21	Primary-amine oxidase
+1.4.3.22	Diamine oxidase
+1.4.3.23	7-chloro-L-tryptophan oxidase
+1.4.3.24	Pseudooxynicotine oxidase
+1.4.4.1	Transferred entry: 1.21.4.1
+1.4.4.2	Glycine dehydrogenase (aminomethyl-transferring)
+1.4.5.1	D-amino acid dehydrogenase (quinone)
+1.4.7.1	Glutamate synthase (ferredoxin)
+1.4.9.1	Methylamine dehydrogenase (amicyanin)
+1.4.9.2	Aralkylamine dehydrogenase (azurin)
+1.4.98.1	Transferred entry: 1.4.9.1
+1.4.99.1	Transferred entry: 1.4.99.6
+1.4.99.2	Taurine dehydrogenase
+1.4.99.3	Transferred entry: 1.4.9.1
+1.4.99.4	Transferred entry: 1.4.9.2
+1.4.99.5	Glycine dehydrogenase (cyanide-forming)
+1.4.99.6	D-arginine dehydrogenase
+1.5.1.1	(NAD(P)H)
+1.5.1.2	Pyrroline-5-carboxylate reductase
+1.5.1.3	Dihydrofolate reductase
+1.5.1.4	Transferred entry: 1.5.1.3
+1.5.1.5	Methylenetetrahydrofolate dehydrogenase (NADP(+))
+1.5.1.6	Formyltetrahydrofolate dehydrogenase
+1.5.1.7	Saccharopine dehydrogenase (NAD(+), L-lysine-forming)
+1.5.1.8	Saccharopine dehydrogenase (NADP(+), L-lysine-forming)
+1.5.1.9	Saccharopine dehydrogenase (NAD(+), L-glutamate-forming)
+1.5.1.10	Saccharopine dehydrogenase (NADP(+), L-glutamate-forming)
+1.5.1.11	D-octopine dehydrogenase
+1.5.1.12	Transferred entry: 1.2.1.88
+1.5.1.13	Transferred entry: 1.17.1.5
+1.5.1.14	Transferred entry: 1.5.1.21
+1.5.1.15	Methylenetetrahydrofolate dehydrogenase (NAD(+))
+1.5.1.16	D-lysopine dehydrogenase
+1.5.1.17	Alanopine dehydrogenase
+1.5.1.18	Ephedrine dehydrogenase
+1.5.1.19	D-nopaline dehydrogenase
+1.5.1.20	Methylenetetrahydrofolate reductase (NAD(P)H)
+1.5.1.21	1-piperideine-2-carboxylate/1-pyrroline-2-carboxylate reductase (NADPH)
+1.5.1.22	Strombine dehydrogenase
+1.5.1.23	Tauropine dehydrogenase
+1.5.1.24	N(5)-(carboxyethyl)ornithine synthase
+1.5.1.25	Thiomorpholine-carboxylate dehydrogenase
+1.5.1.26	Beta-alanopine dehydrogenase
+1.5.1.27	1,2-dehydroreticulinium reductase (NADPH)
+1.5.1.28	Opine dehydrogenase
+1.5.1.29	Transferred entry: 1.5.1.38, 1.5.1.39 and 1.5.1.41
+1.5.1.30	Flavin reductase (NADPH)
+1.5.1.31	Berberine reductase
+1.5.1.32	Vomilenine reductase
+1.5.1.33	Pteridine reductase
+1.5.1.34	6,7-dihydropteridine reductase
+1.5.1.35	Transferred entry: 1.2.1.19
+1.5.1.36	Flavin reductase (NADH)
+1.5.1.37	FAD reductase (NADH)
+1.5.1.38	FMN reductase (NADPH)
+1.5.1.39	FMN reductase (NAD(P)H)
+1.5.1.40	8-hydroxy-5-deazaflavin:NADPH oxidoreductase
+1.5.1.41	Riboflavin reductase (NAD(P)H)
+1.5.1.42	FMN reductase (NADH)
+1.5.1.43	Carboxynorspermidine synthase
+1.5.1.44	Festuclavine dehydrogenase
+1.5.1.45	FAD reductase (NAD(P)H)
+1.5.1.46	Agroclavine dehydrogenase
+1.5.1.47	Dihydromethanopterin reductase (NAD(P)(+))
+1.5.1.48	2-methyl-1-pyrroline reductase
+1.5.1.49	1-pyrroline-2-carboxylate reductase (NAD(P)H)
+1.5.1.50	Dihydromonapterin reductase
+1.5.3.1	Sarcosine oxidase
+1.5.3.2	N-methyl-L-amino-acid oxidase
+1.5.3.3	Deleted entry
+1.5.3.4	N(6)-methyl-lysine oxidase
+1.5.3.5	(S)-6-hydroxynicotine oxidase
+1.5.3.6	(R)-6-hydroxynicotine oxidase
+1.5.3.7	L-pipecolate oxidase
+1.5.3.8	Transferred entry: 1.3.3.8
+1.5.3.9	Transferred entry: 1.21.3.3
+1.5.3.10	Dimethylglycine oxidase
+1.5.3.11	Transferred entry: 1.5.3.13, 1.5.3.14, 1.5.3.15, 1.5.3.16 and 1.5.3.17
+1.5.3.12	Dihydrobenzophenanthridine oxidase
+1.5.3.13	N(1)-acetylpolyamine oxidase
+1.5.3.14	Polyamine oxidase (propane-1,3-diamine-forming)
+1.5.3.15	N(8)-acetylspermidine oxidase (propane-1,3-diamine-forming)
+1.5.3.16	Spermine oxidase
+1.5.3.17	Non-specific polyamine oxidase
+1.5.3.18	L-saccharopine oxidase
+1.5.3.19	4-methylaminobutanoate oxidase (formaldehyde-forming)
+1.5.3.20	N-alkylglycine oxidase
+1.5.3.21	4-methylaminobutanoate oxidase (methylamine-forming)
+1.5.3.22	Coenzyme F420H(2) oxidase
+1.5.4.1	Pyrimidodiazepine synthase
+1.5.5.1	Electron-transferring-flavoprotein dehydrogenase
+1.5.5.2	Proline dehydrogenase
+1.5.7.1	Methylenetetrahydrofolate reductase (ferredoxin)
+1.5.7.2	Coenzyme F420 oxidoreductase (ferredoxin)
+1.5.8.1	Dimethylamine dehydrogenase
+1.5.8.2	Trimethylamine dehydrogenase
+1.5.8.3	Sarcosine dehydrogenase
+1.5.8.4	Dimethylglycine dehydrogenase
+1.5.98.1	Methylenetetrahydromethanopterin dehydrogenase
+1.5.98.2	5,10-methylenetetrahydromethanopterin reductase
+1.5.99.1	Transferred entry: 1.5.8.3
+1.5.99.2	Transferred entry: 1.5.8.4
+1.5.99.3	L-pipecolate dehydrogenase
+1.5.99.4	Nicotine dehydrogenase
+1.5.99.5	Methylglutamate dehydrogenase
+1.5.99.6	Spermidine dehydrogenase
+1.5.99.7	Transferred entry: 1.5.8.2
+1.5.99.8	Transferred entry: 1.5.5.2
+1.5.99.9	Transferred entry: 1.5.98.1
+1.5.99.10	Transferred entry: 1.5.8.1
+1.5.99.11	Transferred entry: 1.5.98.2
+1.5.99.12	Cytokinin dehydrogenase
+1.5.99.13	D-proline dehydrogenase
+1.5.99.14	6-hydroxypseudooxynicotine dehydrogenase
+1.5.99.15	Dihydromethanopterin reductase (acceptor)
+1.6.1.1	NAD(P)(+) transhydrogenase (Si-specific)
+1.6.1.2	NAD(P)(+) transhydrogenase (Re/Si-specific)
+1.6.1.3	NAD(P)(+) transhydrogenase
+1.6.1.4	NAD(P)(+) transhydrogenase (ferredoxin)
+1.6.1.5	Proton-translocating NAD(P)(+) transhydrogenase
+1.6.2.1	Transferred entry: 1.6.99.3
+1.6.2.2	Cytochrome-b5 reductase
+1.6.2.3	Deleted entry
+1.6.2.4	NADPH--hemoprotein reductase
+1.6.2.5	NADPH--cytochrome-c2 reductase
+1.6.2.6	Leghemoglobin reductase
+1.6.3.1	NAD(P)H oxidase (H(2)O(2)-forming)
+1.6.3.2	NAD(P)H oxidase (H(2)O-forming)
+1.6.3.3	NADH oxidase (H(2)O(2)-forming)
+1.6.3.4	NADH oxidase (H(2)O-forming)
+1.6.3.5	Renalase
+1.6.4.1	Transferred entry: 1.8.1.6
+1.6.4.2	Transferred entry: 1.8.1.7
+1.6.4.3	Transferred entry: 1.8.1.4
+1.6.4.4	Transferred entry: 1.8.1.8
+1.6.4.5	Transferred entry: 1.8.1.9
+1.6.4.6	Transferred entry: 1.8.1.10
+1.6.4.7	Transferred entry: 1.8.1.11
+1.6.4.8	Transferred entry: 1.8.1.12
+1.6.4.9	Transferred entry: 1.8.1.13
+1.6.4.10	Transferred entry: 1.8.1.14
+1.6.5.1	Deleted entry
+1.6.5.2	NAD(P)H dehydrogenase (quinone)
+1.6.5.3	NADH:ubiquinone reductase (H(+)-translocating)
+1.6.5.4	Monodehydroascorbate reductase (NADH)
+1.6.5.5	NADPH:quinone reductase
+1.6.5.6	p-benzoquinone reductase (NADPH)
+1.6.5.7	2-hydroxy-1,4-benzoquinone reductase
+1.6.5.8	NADH:ubiquinone reductase (Na(+)-transporting)
+1.6.5.9	NADH:ubiquinone reductase (non-electrogenic)
+1.6.5.10	NADPH dehydrogenase (quinone)
+1.6.5.11	NADH dehydrogenase (quinone)
+1.6.5.12	Demethylphylloquinone reductase
+1.6.6.1	Transferred entry: 1.7.1.1
+1.6.6.2	Transferred entry: 1.7.1.2
+1.6.6.3	Transferred entry: 1.7.1.3
+1.6.6.4	Transferred entry: 1.7.1.4
+1.6.6.5	Transferred entry: 1.7.2.1
+1.6.6.6	Transferred entry: 1.7.1.5
+1.6.6.7	Transferred entry: 1.7.1.6
+1.6.6.8	Transferred entry: 1.7.1.7
+1.6.6.9	Trimethylamine-N-oxide reductase
+1.6.6.10	Transferred entry: 1.7.1.9
+1.6.6.11	Transferred entry: 1.7.1.10
+1.6.6.12	Transferred entry: 1.7.1.11
+1.6.6.13	Transferred entry: 1.7.1.12
+1.6.7.1	Transferred entry: 1.18.1.2
+1.6.7.2	Transferred entry: 1.18.1.1
+1.6.8.1	Transferred entry: 1.5.1.38, 1.5.1.39 and 1.5.1.41
+1.6.8.2	Transferred entry: 1.5.1.30
+1.6.99.1	NADPH dehydrogenase
+1.6.99.2	Transferred entry: 1.6.5.2
+1.6.99.3	NADH dehydrogenase
+1.6.99.4	Transferred entry: 1.18.1.2
+1.6.99.5	Transferred entry: 1.6.5.11
+1.6.99.6	Transferred entry: 1.6.5.10
+1.6.99.7	Transferred entry: 1.5.1.34
+1.6.99.8	Transferred entry: 1.16.1.3
+1.6.99.9	Transferred entry: 1.16.1.4
+1.6.99.10	Transferred entry: 1.5.1.34
+1.6.99.11	Transferred entry: 1.16.1.5
+1.6.99.12	Transferred entry: 1.16.1.6
+1.6.99.13	Transferred entry: 1.16.1.7
+1.7.1.1	Nitrate reductase (NADH)
+1.7.1.2	Nitrate reductase (NAD(P)H)
+1.7.1.3	Nitrate reductase (NADPH)
+1.7.1.4	Nitrite reductase (NAD(P)H)
+1.7.1.5	Hyponitrite reductase
+1.7.1.6	Azobenzene reductase
+1.7.1.7	GMP reductase
+1.7.1.8	Deleted entry
+1.7.1.9	Nitroquinoline-N-oxide reductase
+1.7.1.10	Hydroxylamine reductase (NADH)
+1.7.1.11	4-(dimethylamino)phenylazoxybenzene reductase
+1.7.1.12	N-hydroxy-2-acetamidofluorene reductase
+1.7.1.13	PreQ(1) synthase
+1.7.1.14	Nitric oxide reductase (NAD(P)(+), nitrous oxide-forming)
+1.7.1.15	Nitrite reductase (NADH)
+1.7.2.1	Nitrite reductase (NO-forming)
+1.7.2.2	Nitrite reductase (cytochrome; ammonia-forming)
+1.7.2.3	Trimethylamine-N-oxide reductase (cytochrome c)
+1.7.2.4	Nitrous-oxide reductase
+1.7.2.5	Nitric-oxide reductase (cytochrome c)
+1.7.2.6	Hydroxylamine dehydrogenase
+1.7.3.1	Nitroalkane oxidase
+1.7.3.2	Acetylindoxyl oxidase
+1.7.3.3	Factor independent urate hydroxylase
+1.7.3.4	Transferred entry: 1.7.2.6 and 1.7.3.6
+1.7.3.5	3-aci-nitropropanoate oxidase
+1.7.3.6	Hydroxylamine oxidase (cytochrome)
+1.7.5.1	Nitrate reductase (quinone)
+1.7.5.2	Nitric oxide reductase (menaquinol)
+1.7.6.1	Nitrite dismutase
+1.7.7.1	Ferredoxin--nitrite reductase
+1.7.7.2	Ferredoxin--nitrate reductase
+1.7.99.1	Hydroxylamine reductase
+1.7.99.2	Deleted entry
+1.7.99.3	Transferred entry: 1.7.2.1
+1.7.99.4	Nitrate reductase
+1.7.99.5	Transferred entry: 1.5.1.20
+1.7.99.6	Transferred entry: 1.7.2.4
+1.7.99.7	Transferred entry: 1.7.2.5
+1.7.99.8	Hydrazine oxidoreductase
+1.8.1.1	Deleted entry
+1.8.1.2	Assimilatory sulfite reductase (NADPH)
+1.8.1.3	Hypotaurine dehydrogenase
+1.8.1.4	Dihydrolipoyl dehydrogenase
+1.8.1.5	2-oxopropyl-CoM reductase (carboxylating)
+1.8.1.6	Cystine reductase
+1.8.1.7	Glutathione-disulfide reductase
+1.8.1.8	Protein-disulfide reductase
+1.8.1.9	Thioredoxin-disulfide reductase
+1.8.1.10	CoA-glutathione reductase
+1.8.1.11	Asparagusate reductase
+1.8.1.12	Trypanothione-disulfide reductase
+1.8.1.13	Bis-gamma-glutamylcystine reductase
+1.8.1.14	CoA-disulfide reductase
+1.8.1.15	Mycothione reductase
+1.8.1.16	Glutathione amide reductase
+1.8.1.17	Dimethylsulfone reductase
+1.8.1.18	NAD(P)H sulfur oxidoreductase (CoA-dependent)
+1.8.1.19	Sulfide dehydrogenase
+1.8.2.1	Sulfite dehydrogenase
+1.8.2.2	Thiosulfate dehydrogenase
+1.8.2.3	Sulfide-cytochrome-c reductase (flavocytochrome c)
+1.8.2.4	Dimethyl sulfide:cytochrome c2 reductase
+1.8.3.1	Sulfite oxidase
+1.8.3.2	Thiol oxidase
+1.8.3.3	Glutathione oxidase
+1.8.3.4	Methanethiol oxidase
+1.8.3.5	Prenylcysteine oxidase
+1.8.3.6	Farnesylcysteine lyase
+1.8.4.1	Glutathione--homocystine transhydrogenase
+1.8.4.2	Protein-disulfide reductase (glutathione)
+1.8.4.3	Glutathione--CoA-glutathione transhydrogenase
+1.8.4.4	Glutathione--cystine transhydrogenase
+1.8.4.5	Transferred entry: 1.8.4.13 and 1.8.4.14
+1.8.4.6	Transferred entry: 1.8.4.11
+1.8.4.7	Enzyme-thiol transhydrogenase (glutathione-disulfide)
+1.8.4.8	Phosphoadenylyl-sulfate reductase (thioredoxin)
+1.8.4.9	Adenylyl-sulfate reductase (glutathione)
+1.8.4.10	Adenylyl-sulfate reductase (thioredoxin)
+1.8.4.11	Peptide-methionine (S)-S-oxide reductase
+1.8.4.12	Peptide-methionine (R)-S-oxide reductase
+1.8.4.13	L-methionine (S)-S-oxide reductase
+1.8.4.14	L-methionine (R)-S-oxide reductase
+1.8.5.1	Glutathione dehydrogenase (ascorbate)
+1.8.5.2	Thiosulfate dehydrogenase (quinone)
+1.8.5.3	Dimethylsulfoxide reductase
+1.8.5.4	Sulfide:quinone reductase
+1.8.6.1	Transferred entry: 2.5.1.18
+1.8.7.1	Assimilatory sulfite reductase (ferredoxin)
+1.8.7.2	Ferredoxin:thioredoxin reductase
+1.8.98.1	CoB--CoM heterodisulfide reductase
+1.8.98.2	Sulfiredoxin
+1.8.98.3	Sulfite reductase (coenzyme F420)
+1.8.99.1	Deleted entry
+1.8.99.2	Adenylyl-sulfate reductase
+1.8.99.3	Hydrogensulfite reductase
+1.8.99.4	Transferred entry: 1.8.4.8
+1.8.99.5	Dissimilatory sulfite reductase
+1.9.3.1	Cytochrome-c oxidase
+1.9.3.2	Transferred entry: 1.7.2.1
+1.9.6.1	Nitrate reductase (cytochrome)
+1.9.98.1	Iron--cytochrome-c reductase
+1.9.99.1	Transferred entry: 1.9.98.1
+1.10.1.1	Trans-acenaphthene-1,2-diol dehydrogenase
+1.10.2.1	L-ascorbate--cytochrome-b5 reductase
+1.10.2.2	Quinol--cytochrome-c reductase
+1.10.3.1	Catechol oxidase
+1.10.3.2	Laccase
+1.10.3.3	L-ascorbate oxidase
+1.10.3.4	o-aminophenol oxidase
+1.10.3.5	3-hydroxyanthranilate oxidase
+1.10.3.6	Rifamycin-B oxidase
+1.10.3.7	Transferred entry: 1.21.3.4
+1.10.3.8	Transferred entry: 1.21.3.5
+1.10.3.9	Photosystem II
+1.10.3.10	Ubiquinol oxidase (H(+)-transporting)
+1.10.3.11	Ubiquinol oxidase (non-electrogenic)
+1.10.3.12	Menaquinol oxidase (H(+)-transporting)
+1.10.3.13	Caldariellaquinol oxidase (H(+)-transporting)
+1.10.3.14	Ubiquinol oxidase (electrogenic, non H(+)-transporting)
+1.10.3.15	Grixazone synthase
+1.10.5.1	Ribosyldihydronicotinamide dehydrogenase (quinone)
+1.10.9.1	Plastoquinol--plastocyanin reductase
+1.10.99.1	Transferred entry: 1.10.9.1
+1.10.99.2	Transferred entry: 1.10.5.1
+1.10.99.3	Transferred entry: 1.23.5.1
+1.11.1.1	NADH peroxidase
+1.11.1.2	NADPH peroxidase
+1.11.1.3	Fatty-acid peroxidase
+1.11.1.4	Transferred entry: 1.13.11.11
+1.11.1.5	Cytochrome-c peroxidase
+1.11.1.6	Catalase
+1.11.1.7	Peroxidase
+1.11.1.8	Iodide peroxidase
+1.11.1.9	Glutathione peroxidase
+1.11.1.10	Chloride peroxidase
+1.11.1.11	L-ascorbate peroxidase
+1.11.1.12	Phospholipid-hydroperoxide glutathione peroxidase
+1.11.1.13	Manganese peroxidase
+1.11.1.14	Lignin peroxidase
+1.11.1.15	Peroxiredoxin
+1.11.1.16	Versatile peroxidase
+1.11.1.17	Glutathione amide-dependent peroxidase
+1.11.1.18	Bromide peroxidase
+1.11.1.19	Dye decolorizing peroxidase
+1.11.1.20	Prostamide/prostaglandin F(2-alpha) synthase
+1.11.1.21	Catalase peroxidase
+1.11.1.22	Hydroperoxy fatty acid reductase
+1.11.1.23	(S)-2-hydroxypropylphosphonic acid epoxidase
+1.11.2.1	Unspecific peroxygenase
+1.11.2.2	Myeloperoxidase
+1.11.2.3	Plant seed peroxygenase
+1.11.2.4	Fatty-acid peroxygenase
+1.11.2.5	3-methyl-L-tyrosine peroxygenase
+1.12.1.1	Transferred entry: 1.12.7.2
+1.12.1.2	Hydrogen dehydrogenase
+1.12.1.3	Hydrogen dehydrogenase (NADP(+))
+1.12.1.4	Hydrogenase (NAD(+), ferredoxin)
+1.12.1.5	Hydrogen dehydrogenase (NAD(P)(+))
+1.12.2.1	Cytochrome-c3 hydrogenase
+1.12.5.1	Hydrogen:quinone oxidoreductase
+1.12.7.1	Transferred entry: 1.12.7.2
+1.12.7.2	Ferredoxin hydrogenase
+1.12.98.1	Coenzyme F420 hydrogenase
+1.12.98.2	5,10-methenyltetrahydromethanopterin hydrogenase
+1.12.98.3	Methanosarcina-phenazine hydrogenase
+1.12.98.4	Sulfhydrogenase
+1.12.99.1	Transferred entry: 1.12.98.1
+1.12.99.2	Deleted entry
+1.12.99.3	Transferred entry: 1.12.5.1
+1.12.99.4	Transferred entry: 1.12.98.2
+1.12.99.5	Transferred entry: 1.13.11.47
+1.12.99.6	Hydrogenase (acceptor)
+1.13.1.1	Transferred entry: 1.13.11.1
+1.13.1.2	Transferred entry: 1.13.11.2
+1.13.1.3	Transferred entry: 1.13.11.3
+1.13.1.4	Transferred entry: 1.13.11.4
+1.13.1.5	Transferred entry: 1.13.11.5
+1.13.1.6	Transferred entry: 1.13.11.6
+1.13.1.7	Deleted entry
+1.13.1.8	Transferred entry: 1.13.11.8
+1.13.1.9	Transferred entry: 1.13.11.9
+1.13.1.10	Transferred entry: 1.13.11.10
+1.13.1.11	Transferred entry: 1.13.99.1
+1.13.1.12	Transferred entry: 1.13.11.11
+1.13.1.13	Transferred entry: 1.13.11.12
+1.13.11.1	Catechol 1,2-dioxygenase
+1.13.11.2	Catechol 2,3-dioxygenase
+1.13.11.3	Protocatechuate 3,4-dioxygenase
+1.13.11.4	Gentisate 1,2-dioxygenase
+1.13.11.5	Homogentisate 1,2-dioxygenase
+1.13.11.6	3-hydroxyanthranilate 3,4-dioxygenase
+1.13.11.7	Deleted entry
+1.13.11.8	Protocatechuate 4,5-dioxygenase
+1.13.11.9	2,5-dihydroxypyridine 5,6-dioxygenase
+1.13.11.10	7,8-dihydroxykynurenate 8,8a-dioxygenase
+1.13.11.11	Tryptophan 2,3-dioxygenase
+1.13.11.12	Linoleate 13S-lipoxygenase
+1.13.11.13	Deleted entry
+1.13.11.14	2,3-dihydroxybenzoate 3,4-dioxygenase
+1.13.11.15	3,4-dihydroxyphenylacetate 2,3-dioxygenase
+1.13.11.16	3-carboxyethylcatechol 2,3-dioxygenase
+1.13.11.17	Indole 2,3-dioxygenase
+1.13.11.18	Persulfide dioxygenase
+1.13.11.19	Cysteamine dioxygenase
+1.13.11.20	Cysteine dioxygenase
+1.13.11.21	Transferred entry: 1.13.11.63
+1.13.11.22	Caffeate 3,4-dioxygenase
+1.13.11.23	2,3-dihydroxyindole 2,3-dioxygenase
+1.13.11.24	Quercetin 2,3-dioxygenase
+1.13.11.25	dioxygenase
+1.13.11.26	Peptide-tryptophan 2,3-dioxygenase
+1.13.11.27	4-hydroxyphenylpyruvate dioxygenase
+1.13.11.28	2,3-dihydroxybenzoate 2,3-dioxygenase
+1.13.11.29	Stizolobate synthase
+1.13.11.30	Stizolobinate synthase
+1.13.11.31	Arachidonate 12-lipoxygenase
+1.13.11.32	Transferred entry: 1.13.12.16
+1.13.11.33	Arachidonate 15-lipoxygenase
+1.13.11.34	Arachidonate 5-lipoxygenase
+1.13.11.35	Pyrogallol 1,2-oxygenase
+1.13.11.36	Chloridazon-catechol dioxygenase
+1.13.11.37	Hydroxyquinol 1,2-dioxygenase
+1.13.11.38	1-hydroxy-2-naphthoate 1,2-dioxygenase
+1.13.11.39	Biphenyl-2,3-diol 1,2-dioxygenase
+1.13.11.40	Arachidonate 8-lipoxygenase
+1.13.11.41	2,4'-dihydroxyacetophenone dioxygenase
+1.13.11.42	Deleted entry
+1.13.11.43	Lignostilbene alpha-beta-dioxygenase
+1.13.11.44	Transferred entry: 1.13.11.60 and 5.4.4.6
+1.13.11.45	Linoleate 11-lipoxygenase
+1.13.11.46	4-hydroxymandelate synthase
+1.13.11.47	3-hydroxy-4-oxoquinoline 2,4-dioxygenase
+1.13.11.48	3-hydroxy-2-methylquinolin-4-one 2,4-dioxygenase
+1.13.11.49	Chlorite O(2)-lyase
+1.13.11.50	Acetylacetone-cleaving enzyme
+1.13.11.51	9-cis-epoxycarotenoid dioxygenase
+1.13.11.52	Indoleamine 2,3-dioxygenase
+1.13.11.53	Acireductone dioxygenase (Ni(2+)-requiring)
+1.13.11.54	Acireductone dioxygenase (Fe(2+)-requiring)
+1.13.11.55	Sulfur oxygenase/reductase
+1.13.11.56	1,2-dihydroxynaphthalene dioxygenase
+1.13.11.57	Gallate dioxygenase
+1.13.11.58	Linoleate 9S-lipoxygenase
+1.13.11.59	Torulene dioxygenase
+1.13.11.60	Linoleate 8R-lipoxygenase
+1.13.11.61	Linolenate 9R-lipoxygenase
+1.13.11.62	Linoleate 10R-lipoxygenase
+1.13.11.63	Beta-carotene 15,15'-dioxygenase
+1.13.11.64	5-nitrosalicylate dioxygenase
+1.13.11.65	Carotenoid isomerooxygenase
+1.13.11.66	Hydroquinone 1,2-dioxygenase
+1.13.11.67	8'-apo-beta-carotenoid 14',13'-cleaving dioxygenase
+1.13.11.68	9-cis-beta-carotene 9',10'-cleaving dioxygenase
+1.13.11.69	Carlactone synthase
+1.13.11.70	All-trans-10'-apo-beta-carotenal 13,14-cleaving dioxygenase
+1.13.11.71	Carotenoid-9',10'-cleaving dioxygenase
+1.13.11.72	2-hydroxyethylphosphonate dioxygenase
+1.13.11.73	Methylphosphonate synthase
+1.13.11.74	2-aminophenol 1,6-dioxygenase
+1.13.11.75	All-trans-8'-apo-beta-carotenal 15,15'-oxygenase
+1.13.11.76	2-amino-5-chlorophenol 1,6-dioxygenase
+1.13.11.77	Oleate 10S-lipoxygenase
+1.13.11.78	2-amino-1-hydroxyethylphosphonate dioxygenase (glycine-forming)
+1.13.11.79	5,6-dimethylbenzimidazole synthase
+1.13.11.80	(3,5-dihydroxyphenyl)acetyl-CoA 1,2-dioxygenase
+1.13.11.81	7,8-dihydroneopterin oxygenase
+1.13.11.82	8'-apo-carotenoid 13,14-cleaving dioxygenase
+1.13.12.1	Arginine 2-monooxygenase
+1.13.12.2	Lysine 2-monooxygenase
+1.13.12.3	Tryptophan 2-monooxygenase
+1.13.12.4	Lactate 2-monooxygenase
+1.13.12.5	Renilla-luciferin 2-monooxygenase
+1.13.12.6	Cypridina-luciferin 2-monooxygenase
+1.13.12.7	Photinus-luciferin 4-monooxygenase (ATP-hydrolyzing)
+1.13.12.8	Watasenia-luciferin 2-monooxygenase
+1.13.12.9	Phenylalanine 2-monooxygenase
+1.13.12.10	Deleted entry
+1.13.12.11	Transferred entry: 1.14.13.8
+1.13.12.12	Transferred entry: 1.13.11.67
+1.13.12.13	Oplophorus-luciferin 2-monooxygenase
+1.13.12.14	Transferred entry: 1.14.13.122
+1.13.12.15	3,4-dihydroxyphenylalanine oxidative deaminase
+1.13.12.16	Nitronate monooxygenase
+1.13.12.17	Dichloroarcyriaflavin A synthase
+1.13.12.18	Dinoflagellate luciferase
+1.13.12.19	2-oxuglutarate dioxygenase (ethylene-forming)
+1.13.12.20	Noranthrone monooxygenase
+1.13.12.21	Tetracenomycin-F1 monooxygenase
+1.13.12.22	Deoxynogalonate monooxygenase
+1.13.99.1	Inositol oxygenase
+1.13.99.2	Transferred entry: 1.14.12.10
+1.13.99.3	Tryptophan 2'-dioxygenase
+1.13.99.4	Transferred entry: 1.14.12.9
+1.13.99.5	Transferred entry: 1.13.11.47
+1.14.1.1	Transferred entry: 1.14.14.1
+1.14.1.2	Transferred entry: 1.14.13.9
+1.14.1.3	Transferred entry: 1.14.14.17 and 5.4.99.7
+1.14.1.4	Transferred entry: 1.14.99.2
+1.14.1.5	Transferred entry: 1.14.13.5
+1.14.1.6	Transferred entry: 1.14.15.4
+1.14.1.7	Transferred entry: 1.14.14.19
+1.14.1.8	Transferred entry: 1.14.14.16
+1.14.1.9	Deleted entry
+1.14.1.10	Transferred entry: 1.14.99.11
+1.14.1.11	Deleted entry
+1.14.2.1	Transferred entry: 1.14.17.1
+1.14.2.2	Transferred entry: 1.13.11.27
+1.14.3.1	Transferred entry: 1.14.16.1
+1.14.11.1	Gamma-butyrobetaine dioxygenase
+1.14.11.2	Procollagen-proline dioxygenase
+1.14.11.3	Pyrimidine-deoxynucleoside 2'-dioxygenase
+1.14.11.4	Procollagen-lysine 5-dioxygenase
+1.14.11.5	Transferred entry: 1.14.11.6
+1.14.11.6	Thymine dioxygenase
+1.14.11.7	Procollagen-proline 3-dioxygenase
+1.14.11.8	Trimethyllysine dioxygenase
+1.14.11.9	Flavanone 3-dioxygenase
+1.14.11.10	Pyrimidine-deoxynucleoside 1'-dioxygenase
+1.14.11.11	Hyoscyamine (6S)-dioxygenase
+1.14.11.12	Gibberellin-44 dioxygenase
+1.14.11.13	Gibberellin 2-beta-dioxygenase
+1.14.11.14	6-beta-hydroxyhyoscyamine epoxidase
+1.14.11.15	Gibberellin 3-beta-dioxygenase
+1.14.11.16	Peptide-aspartate beta-dioxygenase
+1.14.11.17	Taurine dioxygenase
+1.14.11.18	Phytanoyl-CoA dioxygenase
+1.14.11.19	Leucocyanidin oxygenase
+1.14.11.20	Deacetoxyvindoline 4-hydroxylase
+1.14.11.21	Clavaminate synthase
+1.14.11.22	Flavone synthase
+1.14.11.23	Flavonol synthase
+1.14.11.24	2'-deoxymugineic-acid 2'-dioxygenase
+1.14.11.25	Mugineic-acid 3-dioxygenase
+1.14.11.26	Deacetoxycephalosporin-C hydroxylase
+1.14.11.27	[Histone H3]-lysine-36 demethylase
+1.14.11.28	Proline 3-hydroxylase
+1.14.11.29	Hypoxia-inducible factor-proline dioxygenase
+1.14.11.30	Hypoxia-inducible factor-asparagine dioxygenase
+1.14.11.31	Thebaine 6-O-demethylase
+1.14.11.32	Codeine 3-O-demethylase
+1.14.11.33	DNA oxidative demethylase
+1.14.11.34	forming)
+1.14.11.35	1-deoxypentalenic acid 11-beta-hydroxylase
+1.14.11.36	Pentalenolactone F synthase
+1.14.11.37	Kanamycin B dioxygenase
+1.14.11.38	Verruculogen synthase
+1.14.11.39	L-asparagine oxygenase
+1.14.11.40	Enduracididine beta-hydroxylase
+1.14.11.41	L-arginine hydroxylase
+1.14.11.42	tRNA(Phe) (7-(3-amino-3-carboxypropyl)wyosine(37)-C(2))-hydroxylase
+1.14.11.43	(S)-dichlorprop dioxygenase (2-oxoglutarate)
+1.14.11.44	(R)-dichlorprop dioxygenase (2-oxoglutarate)
+1.14.11.45	L-isoleucine 4-hydroxylase
+1.14.11.46	2-aminoethylphosphonate dioxygenase
+1.14.11.47	50S ribosomal protein L16 3-hydroxylase
+1.14.11.48	Xanthine dioxygenase
+1.14.11.49	Uridine-5'-phosphate dioxygenase
+1.14.12.1	Anthranilate 1,2-dioxygenase (deaminating, decarboxylating)
+1.14.12.2	Transferred entry: 1.14.13.35
+1.14.12.3	Benzene 1,2-dioxygenase
+1.14.12.4	3-hydroxy-2-methylpyridinecarboxylate dioxygenase
+1.14.12.5	5-pyridoxate dioxygenase
+1.14.12.6	Transferred entry: 1.14.13.66
+1.14.12.7	Phthalate 4,5-dioxygenase
+1.14.12.8	4-sulfobenzoate 3,4-dioxygenase
+1.14.12.9	4-chlorophenylacetate 3,4-dioxygenase
+1.14.12.10	Benzoate 1,2-dioxygenase
+1.14.12.11	Toluene dioxygenase
+1.14.12.12	Naphthalene 1,2-dioxygenase
+1.14.12.13	2-halobenzoate 1,2-dioxygenase
+1.14.12.14	2-aminobenzenesulfonate 2,3-dioxygenase
+1.14.12.15	Terephthalate 1,2-dioxygenase
+1.14.12.16	2-hydroxyquinoline 5,6-dioxygenase
+1.14.12.17	Nitric oxide dioxygenase
+1.14.12.18	Biphenyl 2,3-dioxygenase
+1.14.12.19	3-phenylpropanoate dioxygenase
+1.14.12.20	Pheophorbide a oxygenase
+1.14.12.21	Transferred entry: 1.14.13.208
+1.14.12.22	Carbazole 1,9a-dioxygenase
+1.14.12.23	Nitroarene dioxygenase
+1.14.12.24	2,4-dinitrotoluene dioxygenase
+1.14.13.1	Salicylate 1-monooxygenase
+1.14.13.2	4-hydroxybenzoate 3-monooxygenase
+1.14.13.3	Transferred entry: 1.14.14.9
+1.14.13.4	Melilotate 3-monooxygenase
+1.14.13.5	Imidazoleacetate 4-monooxygenase
+1.14.13.6	Orcinol 2-monooxygenase
+1.14.13.7	Phenol 2-monooxygenase (NADPH)
+1.14.13.8	Flavin-containing monooxygenase
+1.14.13.9	Kynurenine 3-monooxygenase
+1.14.13.10	2,6-dihydroxypyridine 3-monooxygenase
+1.14.13.11	Trans-cinnamate 4-monooxygenase
+1.14.13.12	Benzoate 4-monooxygenase
+1.14.13.13	Calcidiol 1-monooxygenase
+1.14.13.14	Trans-cinnamate 2-monooxygenase
+1.14.13.15	Cholestanetriol 26-monooxygenase
+1.14.13.16	Cyclopentanone monooxygenase
+1.14.13.17	Cholesterol 7-alpha-monooxygenase
+1.14.13.18	4-hydroxyphenylacetate 1-monooxygenase
+1.14.13.19	Taxifolin 8-monooxygenase
+1.14.13.20	2,4-dichlorophenol 6-monooxygenase
+1.14.13.21	Flavonoid 3'-monooxygenase
+1.14.13.22	Cyclohexanone monooxygenase
+1.14.13.23	3-hydroxybenzoate 4-monooxygenase
+1.14.13.24	3-hydroxybenzoate 6-monooxygenase
+1.14.13.25	Methane monooxygenase (soluble)
+1.14.13.26	Transferred entry: 1.14.18.4
+1.14.13.27	4-aminobenzoate 1-monooxygenase
+1.14.13.28	3,9-dihydroxypterocarpan 6A-monooxygenase
+1.14.13.29	4-nitrophenol 2-monooxygenase
+1.14.13.30	Leukotriene-B(4) 20-monooxygenase
+1.14.13.31	2-nitrophenol 2-monooxygenase
+1.14.13.32	Albendazole monooxygenase
+1.14.13.33	4-hydroxybenzoate 3-monooxygenase (NAD(P)H)
+1.14.13.34	Leukotriene-E(4) 20-monooxygenase
+1.14.13.35	Anthranilate 3-monooxygenase (deaminating)
+1.14.13.36	5-O-(4-coumaroyl)-D-quinate 3'-monooxygenase
+1.14.13.37	Methyltetrahydroprotoberberine 14-monooxygenase
+1.14.13.38	Anhydrotetracycline monooxygenase
+1.14.13.39	Nitric-oxide synthase (NADPH)
+1.14.13.40	Anthraniloyl-CoA monooxygenase
+1.14.13.41	Tyrosine N-monooxygenase
+1.14.13.42	Deleted entry
+1.14.13.43	Questin monooxygenase
+1.14.13.44	2-hydroxybiphenyl 3-monooxygenase
+1.14.13.45	Transferred entry: 1.14.18.2
+1.14.13.46	(-)-menthol monooxygenase
+1.14.13.47	(S)-limonene 3-monooxygenase
+1.14.13.48	(S)-limonene 6-monooxygenase
+1.14.13.49	(S)-limonene 7-monooxygenase
+1.14.13.50	Pentachlorophenol monooxygenase
+1.14.13.51	6-oxocineole dehydrogenase
+1.14.13.52	Isoflavone 3'-hydroxylase
+1.14.13.53	4'-methoxyisoflavone 2'-hydroxylase
+1.14.13.54	Ketosteroid monooxygenase
+1.14.13.55	Protopine 6-monooxygenase
+1.14.13.56	Dihydrosanguinarine 10-monooxygenase
+1.14.13.57	Dihydrochelirubine 12-monooxygenase
+1.14.13.58	Benzoyl-CoA 3-monooxygenase
+1.14.13.59	L-lysine N(6)-monooxygenase (NADPH)
+1.14.13.60	Transferred entry: 1.14.13.100
+1.14.13.61	2-hydroxyquinoline 8-monooxygenase
+1.14.13.62	4-hydroxyquinoline 3-monooxygenase
+1.14.13.63	3-hydroxyphenylacetate 6-hydroxylase
+1.14.13.64	4-hydroxybenzoate 1-hydroxylase
+1.14.13.65	Deleted entry
+1.14.13.66	2-hydroxycyclohexanone 2-monooxygenase
+1.14.13.67	Quinine 3-monooxygenase
+1.14.13.68	4-hydroxyphenylacetaldehyde oxime monooxygenase
+1.14.13.69	Alkene monooxygenase
+1.14.13.70	Sterol 14-alpha-demethylase
+1.14.13.71	N-methylcoclaurine 3'-monooxygenase
+1.14.13.72	Methylsterol monooxygenase
+1.14.13.73	Tabersonine 16-hydroxylase
+1.14.13.74	7-deoxyloganin 7-hydroxylase
+1.14.13.75	Vinorine hydroxylase
+1.14.13.76	Taxane 10-beta-hydroxylase
+1.14.13.77	Taxane 13-alpha-hydroxylase
+1.14.13.78	Ent-kaurene oxidase
+1.14.13.79	Ent-kaurenoic acid oxidase
+1.14.13.80	(R)-limonene 6-monooxygenase
+1.14.13.81	Magnesium-protoporphyrin IX monomethyl ester (oxidative) cyclase
+1.14.13.82	Vanillate monooxygenase
+1.14.13.83	Precorrin-3B synthase
+1.14.13.84	4-hydroxyacetophenone monooxygenase
+1.14.13.85	Glyceollin synthase
+1.14.13.86	Transferred entry: 1.14.13.136
+1.14.13.87	Licodione synthase
+1.14.13.88	Flavonoid 3',5'-hydroxylase
+1.14.13.89	Isoflavone 2'-hydroxylase
+1.14.13.90	Zeaxanthin epoxidase
+1.14.13.91	Deoxysarpagine hydroxylase
+1.14.13.92	Phenylacetone monooxygenase
+1.14.13.93	(+)-abscisic acid 8'-hydroxylase
+1.14.13.94	Lithocholate 6-beta-hydroxylase
+1.14.13.95	Transferred entry: 1.14.18.8
+1.14.13.96	5-beta-cholestane-3-alpha,7-alpha-diol 12-alpha-hydroxylase
+1.14.13.97	Taurochenodeoxycholate 6-alpha-hydroxylase
+1.14.13.98	Cholesterol 24-hydroxylase
+1.14.13.99	24-hydroxycholesterol 7-alpha-hydroxylase
+1.14.13.100	25/26-hydroxycholesterol 7-alpha-hydroxylase
+1.14.13.101	Senecionine N-oxygenase
+1.14.13.102	Psoralen synthase
+1.14.13.103	8-dimethylallylnaringenin 2'-hydroxylase
+1.14.13.104	(+)-menthofuran synthase
+1.14.13.105	Monocyclic monoterpene ketone monooxygenase
+1.14.13.106	Epi-isozizaene 5-monooxygenase
+1.14.13.107	Limonene 1,2-monooxygenase
+1.14.13.108	Abieta-7,13-diene hydroxylase
+1.14.13.109	Abieta-7,13-dien-18-ol hydroxylase
+1.14.13.110	Geranylgeraniol 18-hydroxylase
+1.14.13.111	Methanesulfonate monooxygenase
+1.14.13.112	3-epi-6-deoxocathasterone 23-monooxygenase
+1.14.13.113	FAD-dependent urate hydroxylase
+1.14.13.114	6-hydroxynicotinate 3-monooxygenase
+1.14.13.115	Angelicin synthase
+1.14.13.116	Geranylhydroquinone 3''-hydroxylase
+1.14.13.117	Isoleucine N-monooxygenase
+1.14.13.118	Valine N-monooxygenase
+1.14.13.119	5-epiaristolochene 1,3-dihydroxylase
+1.14.13.120	Costunolide synthase
+1.14.13.121	Premnaspirodiene oxygenase
+1.14.13.122	Chlorophyllide-a oxygenase
+1.14.13.123	Germacrene A hydroxylase
+1.14.13.124	Phenylalanine N-monooxygenase
+1.14.13.125	Tryptophan N-monooxygenase
+1.14.13.126	Vitamin D(3) 24-hydroxylase
+1.14.13.127	3-(3-hydroxy-phenyl)propanoic acid hydroxylase
+1.14.13.128	7-methylxanthine demethylase
+1.14.13.129	Beta-carotene 3-hydroxylase
+1.14.13.130	Pyrrole-2-carboxylate monooxygenase
+1.14.13.131	Dimethyl-sulfide monooxygenase
+1.14.13.132	Transferred entry: 1.14.14.17
+1.14.13.133	Pentalenene oxygenase
+1.14.13.134	Beta-amyrin 11-oxidase
+1.14.13.135	1-hydroxy-2-naphthoate hydroxylase
+1.14.13.136	2-hydroxyisoflavanone synthase
+1.14.13.137	Indole-2-monooxygenase
+1.14.13.138	Indolin-2-one monooxygenase
+1.14.13.139	3-hydroxyindolin-2-one monooxygenase
+1.14.13.140	2-hydroxy-1,4-benzoxazin-3-one monooxygenase
+1.14.13.141	Cholest-4-en-3-one 26-monooxygenase
+1.14.13.142	3-ketosteroid 9-alpha-monooxygenase
+1.14.13.143	Ent-isokaurene C2-hydroxylase
+1.14.13.144	9-beta-pimara-7,15-diene oxidase
+1.14.13.145	Ent-cassa-12,15-diene 11-hydroxylase
+1.14.13.146	Taxoid 14-beta-hydroxylase
+1.14.13.147	Taxoid 7-beta-hydroxylase
+1.14.13.148	Trimethylamine monooxygenase
+1.14.13.149	Phenylacetyl-CoA 1,2-epoxidase
+1.14.13.150	Alpha-humulene 10-hydroxylase
+1.14.13.151	Linalool 8-monooxygenase
+1.14.13.152	Geraniol 8-hydroxylase
+1.14.13.153	(+)-sabinene 3-hydroxylase
+1.14.13.154	Erythromycin 12 hydroxylase
+1.14.13.155	Alpha-pinene monooxygenase
+1.14.13.156	1,8-cineole 2-endo-monooxygenase
+1.14.13.157	1,8-cineole 2-exo-monooxygenase
+1.14.13.158	Amorpha-4,11-diene 12 monooxygenase
+1.14.13.159	Vitamin D 25-hydroxylase
+1.14.13.160	(2,2,3-trimethyl-5-oxocyclopent-3-enyl)acetyl-CoA 1,5-monooxygenase
+1.14.13.161	(+)-camphor 6-exo-hydroxylase
+1.14.13.162	2,5-diketocamphane 1,2-monooxygenase
+1.14.13.163	6-hydroxy-3-succinoylpyridine 3-monooxygenase
+1.14.13.164	Transferred entry: 1.13.11.65
+1.14.13.165	Nitric-oxide synthase (NAD(P)H)
+1.14.13.166	4-nitrocatechol 4-monooxygenase
+1.14.13.167	4-nitrophenol 4-monooxygenase
+1.14.13.168	Indole-3-pyruvate monooxygenase
+1.14.13.169	Transferred entry: 1.14.18.5
+1.14.13.170	Pentalenolactone D synthase
+1.14.13.171	Neopentalenolactone D synthase
+1.14.13.172	Salicylate 5-hydroxylase
+1.14.13.173	11-oxo-beta-amyrin 30-oxidase
+1.14.13.174	Averantin hydroxylase
+1.14.13.175	Aflatoxin B synthase
+1.14.13.176	Tryprostatin B 6-hydroxylase
+1.14.13.177	Fumitremorgin C monooxygenase
+1.14.13.178	Methylxanthine N(1)-demethylase
+1.14.13.179	Methylxanthine N(3)-demethylase
+1.14.13.180	Aklavinone 12-hydroxylase
+1.14.13.181	13-deoxydaunorubicin hydroxylase
+1.14.13.182	2-heptyl-3-hydroxy-4(1H)-quinolone synthase
+1.14.13.183	Dammarenediol 12-hydroxylase
+1.14.13.184	Protopanaxadiol 6-hydroxylase
+1.14.13.185	Pikromycin synthase
+1.14.13.186	20-oxo-5-O-mycaminosyltylactone 23-monooxygenase
+1.14.13.187	L-evernosamine nitrososynthase
+1.14.13.188	6-deoxyerythronolide B hydroxylase
+1.14.13.189	5-methyl-1-naphthoate 3-hydroxylase
+1.14.13.190	Ferruginol synthase
+1.14.13.191	Ent-sandaracopimaradiene 3-hydroxylase
+1.14.13.192	Oryzalexin E synthase
+1.14.13.193	Oryzalexin D synthase
+1.14.13.194	Phylloquinone omega-hydroxylase
+1.14.13.195	L-ornithine N(5)-monooxygenase (NADPH)
+1.14.13.196	L-ornithine N(5)-monooxygenase (NAD(P)H)
+1.14.13.197	Dihydromonacolin L hydroxylase
+1.14.13.198	Monacolin L hydroxylase
+1.14.13.199	Docosahexaenoic acid omega-hydroxylase
+1.14.13.200	Tetracenomycin A2 monooxygenase-diooxygenase
+1.14.13.201	Beta-amyrin 28-monooxygenase
+1.14.13.202	Methyl farnesoate epoxidase
+1.14.13.203	Farnesoate epoxidase
+1.14.13.204	Long-chain acyl-CoA omega-monooxygenase
+1.14.13.205	Long-chain fatty acid omega-monooxygenase
+1.14.13.206	Laurate 7-monooxygenase
+1.14.13.207	Ipsdienol synthase
+1.14.13.208	Benzoyl-CoA 2,3-epoxidase
+1.14.13.209	Salicyloyl-CoA 5-hydroxylase
+1.14.14.1	Unspecific monooxygenase
+1.14.14.2	Transferred entry: 1.14.14.1
+1.14.14.3	Alkanal monooxygenase (FMN-linked)
+1.14.14.4	Transferred entry: 1.14.15.7
+1.14.14.5	Alkanesulfonate monooxygenase
+1.14.14.6	Transferred entry: 1.14.13.111
+1.14.14.7	Transferred entry: 1.14.19.9
+1.14.14.8	Anthranilate 3-monooxygenase (FAD)
+1.14.14.9	4-hydroxyphenylacetate 3-monooxygenase
+1.14.14.10	Nitrilotriacetate monooxygenase
+1.14.14.11	Styrene monooxygenase
+1.14.14.12	3-hydroxy-9,10-secoandrosta-1,3,5(10)-triene-9,17-dione monooxygenase
+1.14.14.13	monooxygenase
+1.14.14.14	Aromatase
+1.14.14.15	protein SgcC2] monooxygenase
+1.14.14.16	Steroid 21-monooxygenase
+1.14.14.17	Squalene monooxygenase
+1.14.14.18	Heme oxygenase (biliverdin-producing)
+1.14.14.19	Steroid 17-alpha-monooxygenase
+1.14.15.1	Camphor 5-monooxygenase
+1.14.15.2	Transferred entry: 1.14.13.162
+1.14.15.3	Alkane 1-monooxygenase
+1.14.15.4	Steroid 11-beta-monooxygenase
+1.14.15.5	Corticosterone 18-monooxygenase
+1.14.15.6	Cholesterol monooxygenase (side-chain-cleaving)
+1.14.15.7	Choline monooxygenase
+1.14.15.8	Steroid 15-beta-monooxygenase
+1.14.15.9	Spheroidene monooxygenase
+1.14.15.10	(+)-camphor 6-endo-hydroxylase
+1.14.15.11	Pentalenic acid synthase
+1.14.15.12	Pimeloyl-[acyl-carrier protein] synthase
+1.14.15.13	Pulcherriminic acid synthase
+1.14.15.14	Methyl-branched lipid omega-hydroxylase
+1.14.16.1	Phenylalanine 4-monooxygenase
+1.14.16.2	Tyrosine 3-monooxygenase
+1.14.16.3	Anthranilate 3-monooxygenase
+1.14.16.4	Tryptophan 5-monooxygenase
+1.14.16.5	Alkylglycerol monooxygenase
+1.14.16.6	Mandelate 4-monooxygenase
+1.14.16.7	Phenylalanine 3-monooxygenase
+1.14.17.1	Dopamine beta-monooxygenase
+1.14.17.2	Transferred entry: 1.14.18.1
+1.14.17.3	Peptidylglycine monooxygenase
+1.14.17.4	Aminocyclopropanecarboxylate oxidase
+1.14.18.1	Tyrosinase
+1.14.18.2	CMP-N-acetylneuraminate monooxygenase
+1.14.18.3	Methane monooxygenase (particulate)
+1.14.18.4	Phosphatidylcholine 12-monooxygenase
+1.14.18.5	Sphingolipid C4-monooxygenase
+1.14.18.6	4-hydroxysphinganine ceramide fatty acyl 2-hydroxylase
+1.14.18.7	Dihydroceramide fatty acyl 2-hydroxylase
+1.14.18.8	7-alpha-hydroxycholest-4-en-3-one 12-alpha-hydroxylase
+1.14.19.1	Stearoyl-CoA 9-desaturase
+1.14.19.2	Stearoyl-[acyl-carrier-protein] 9-desaturase
+1.14.19.3	Acyl-CoA 6-desaturase
+1.14.19.4	Acyl-lipid (11-3)-desaturase
+1.14.19.5	Acyl-CoA 11-(Z)-desaturase
+1.14.19.6	Acyl-CoA (9+3)-desaturase
+1.14.19.7	Transferred entry: 1.11.1.23
+1.14.19.8	Pentalenolactone synthase
+1.14.19.9	Tryptophan 7-halogenase
+1.14.19.10	Icosanoyl-CoA 5-desaturase
+1.14.19.11	Acyl-[acyl-carrier-protein] 4-desaturase
+1.14.19.12	Acyl-lipid omega-(9-4) desaturase
+1.14.19.13	Acyl-CoA 15-desaturase
+1.14.19.14	Linoleoyl-lipid Delta(9) conjugase
+1.14.19.15	(11Z)-hexadec-11-enoyl-CoA conjugase
+1.14.19.16	Linoleoyl-lipid Delta(12) conjugase (11E,13Z-forming)
+1.14.19.17	Sphingolipid 4-desaturase
+1.14.19.18	Sphingolipid 8-(E)-desaturase
+1.14.19.19	Sphingolipid 10-desaturase
+1.14.19.20	Delta(7)-sterol 5(6)-desaturase
+1.14.19.21	Cholesterol 7-desaturase
+1.14.19.22	Acyl-lipid omega-6 desaturase (cytochrome b5)
+1.14.19.23	Acyl-lipid (n+3)-(Z)-desaturase (ferredoxin)
+1.14.19.24	Acyl-CoA 11-(E)-desaturase
+1.14.19.25	Acyl-lipid omega-3 desaturase (cytochrome b5)
+1.14.19.26	Acyl-[acyl-carrier-protein] 6-desaturase
+1.14.19.27	sn-2 palmitoyl-lipid 9-desaturase
+1.14.19.28	sn-1 stearoyl-lipid 9-desaturase
+1.14.19.29	Sphingolipid 8-(E/Z)-desaturase
+1.14.19.30	Acyl-lipid (8-3)-desaturase
+1.14.19.31	Acyl-lipid (7-3)-desaturase
+1.14.19.32	Palmitoyl-CoA 14-(E/Z)-desaturase
+1.14.19.33	Delta(12) acyl-lipid conjugase (11E,13E-forming)
+1.14.19.34	Acyl-lipid (9+3)-(E)-desaturase
+1.14.19.35	sn-2 acyl-lipid omega-3 desaturase (ferredoxin)
+1.14.19.36	sn-1 acyl-lipid omega-3 desaturase (ferredoxin)
+1.14.19.37	Acyl-CoA 5-desaturase
+1.14.19.38	Acyl-lipid Delta(6)-acetylenase
+1.14.19.39	Acyl-lipid Delta(12)-acetylenase
+1.14.19.40	Hex-5-enoyl-[acyl-carrier protein] acetylenase
+1.14.19.41	Sterol 22-desaturase
+1.14.19.42	Palmitoyl-[glycerolipid] 7-desaturase
+1.14.19.43	Palmitoyl-[glycerolipid] 3-(E)-desaturase
+1.14.19.44	Acyl-CoA (8-3)-desaturase
+1.14.19.45	sn-1 oleoyl-lipid 12-desaturase
+1.14.19.46	sn-1 linoleoyl-lipid 6-desaturase
+1.14.19.47	Acyl-lipid (9-3)-desaturase
+1.14.20.1	Deacetoxycephalosporin-C synthase
+1.14.20.2	2,4-dihydroxy-1,4-benzoxazin-3-one-glucoside dioxygenase
+1.14.20.3	(5R)-carbapenem-3-carboxylate synthase
+1.14.21.1	(S)-stylopine synthase
+1.14.21.2	(S)-cheilanthifoline synthase
+1.14.21.3	Berbamunine synthase
+1.14.21.4	Salutaridine synthase
+1.14.21.5	(S)-canadine synthase
+1.14.21.6	Transferred entry: 1.14.19.20
+1.14.21.7	Biflaviolin synthase
+1.14.21.8	Pseudobaptigenin synthase
+1.14.21.9	Mycocyclosin synthase
+1.14.21.10	Fumitremorgin C synthase
+1.14.99.1	Prostaglandin-endoperoxide synthase
+1.14.99.2	Kynurenine 7,8-hydroxylase
+1.14.99.3	Transferred entry: 1.14.14.18
+1.14.99.4	Progesterone monooxygenase
+1.14.99.5	Transferred entry: 1.14.19.1
+1.14.99.6	Transferred entry: 1.14.19.2
+1.14.99.7	Transferred entry: 1.14.14.17
+1.14.99.8	Transferred entry: 1.14.14.1
+1.14.99.9	Transferred entry: 1.14.14.19
+1.14.99.10	Transferred entry: 1.14.14.16
+1.14.99.11	Estradiol 6-beta-monooxygenase
+1.14.99.12	Androst-4-ene-3,17-dione monooxygenase
+1.14.99.13	Transferred entry: 1.14.13.23
+1.14.99.14	Progesterone 11-alpha-monooxygenase
+1.14.99.15	4-methoxybenzoate monooxygenase (O-demethylating)
+1.14.99.16	Transferred entry: 1.14.13.72
+1.14.99.17	Transferred entry: 1.14.16.5
+1.14.99.18	Deleted entry
+1.14.99.19	Plasmanylethanolamine desaturase
+1.14.99.20	Phylloquinone monooxygenase (2,3-epoxidizing)
+1.14.99.21	Latia-luciferin monooxygenase (demethylating)
+1.14.99.22	Ecdysone 20-monooxygenase
+1.14.99.23	3-hydroxybenzoate 2-monooxygenase
+1.14.99.24	Steroid 9-alpha-monooxygenase
+1.14.99.25	Transferred entry: 1.14.19.3
+1.14.99.26	2-hydroxypyridine 5-monooxygenase
+1.14.99.27	Juglone 3-monooxygenase
+1.14.99.28	Transferred entry: 1.14.13.151
+1.14.99.29	Deoxyhypusine monooxygenase
+1.14.99.30	Transferred entry: 1.3.5.6
+1.14.99.31	Transferred entry: 1.14.19.24
+1.14.99.32	Transferred entry: 1.14.19.5
+1.14.99.33	Transferred entry: 1.14.19.39
+1.14.99.34	Monoprenyl isoflavone epoxidase
+1.14.99.35	Thiophene-2-carbonyl-CoA monooxygenase
+1.14.99.36	Beta-carotene 15,15'-monooxygenase
+1.14.99.37	Taxadiene 5-alpha-hydroxylase
+1.14.99.38	Cholesterol 25-hydroxylase
+1.14.99.39	Ammonia monooxygenase
+1.14.99.40	Transferred entry: 1.13.11.79
+1.14.99.41	Transferred entry: 1.13.11.75
+1.14.99.42	Zeaxanthin 7,8-dioxygenase
+1.14.99.43	Beta-amyrin 24-hydroxylase
+1.14.99.44	Diapolycopene oxygenase
+1.14.99.45	Carotene epsilon-monooxygenase
+1.14.99.46	Pyrimidine monooxygenase
+1.14.99.47	(+)-larreatricin hydroxylase
+1.14.99.48	Heme oxygenase (staphylobilin-producing)
+1.14.99.49	2-hydroxy-5-methyl-1-naphthoate 7-hydroxylase
+1.14.99.50	Gamma-glutamyl hercynylcysteine S-oxide synthase
+1.14.99.51	Hercynylcysteine S-oxide synthase
+1.14.99.52	L-cysteinyl-L-histidinylsulfoxide synthase
+1.15.1.1	Superoxide dismutase
+1.15.1.2	Superoxide reductase
+1.16.1.1	Mercury(II) reductase
+1.16.1.2	Diferric-transferrin reductase
+1.16.1.3	Aquacobalamin reductase
+1.16.1.4	Cob(II)alamin reductase
+1.16.1.5	Aquacobalamin reductase (NADPH)
+1.16.1.6	Cyanocobalamin reductase (cyanide-eliminating)
+1.16.1.7	Ferric-chelate reductase (NADH)
+1.16.1.8	[Methionine synthase] reductase
+1.16.1.9	Ferric-chelate reductase (NADPH)
+1.16.1.10	Ferric-chelate reductase (NAD(P)H)
+1.16.3.1	Ferroxidase
+1.16.3.2	Bacterial non-heme ferritin
+1.16.5.1	Ascorbate ferrireductase (transmembrane)
+1.16.8.1	Cob(II)yrinic acid a,c-diamide reductase
+1.16.9.1	Iron:rusticyanin reductase
+1.16.98.1	Transferred entry: 1.16.9.1
+1.17.1.1	CDP-4-dehydro-6-deoxyglucose reductase
+1.17.1.2	4-hydroxy-3-methylbut-2-enyl diphosphate reductase
+1.17.1.3	Leucoanthocyanidin reductase
+1.17.1.4	Xanthine dehydrogenase
+1.17.1.5	Nicotinate dehydrogenase
+1.17.1.6	Transferred entry: 1.17.98.1
+1.17.1.7	Transferred entry: 1.2.1.91
+1.17.1.8	4-hydroxy-tetrahydrodipicolinate reductase
+1.17.2.1	Nicotinate dehydrogenase (cytochrome)
+1.17.2.2	Lupanine 17-hydroxylase (cytochrome c)
+1.17.3.1	Pteridine oxidase
+1.17.3.2	Xanthine oxidase
+1.17.3.3	6-hydroxynicotinate dehydrogenase
+1.17.4.1	Ribonucleoside-diphosphate reductase
+1.17.4.2	Ribonucleoside-triphosphate reductase
+1.17.4.3	Transferred entry: 1.17.7.1
+1.17.4.4	Vitamin-K-epoxide reductase (warfarin-sensitive)
+1.17.4.5	Vitamin-K-epoxide reductase (warfarin-insensitive)
+1.17.5.1	Phenylacetyl-CoA dehydrogenase
+1.17.5.2	Caffeine dehydrogenase
+1.17.7.1	(E)-4-hydroxy-3-methylbut-2-enyl-diphosphate synthase (ferredoxin)
+1.17.7.2	7-hydroxymethyl chlorophyll a reductase
+1.17.7.3	(E)-4-hydroxy-3-methylbut-2-enyl-diphosphate synthase (flavodoxin)
+1.17.98.1	Bile-acid 7-alpha-dehydroxylase
+1.17.99.1	4-methylphenol dehydrogenase (hydroxylating)
+1.17.99.2	Ethylbenzene hydroxylase
+1.17.99.3	24-hydroxylase
+1.17.99.4	Uracil/thymine dehydrogenase
+1.17.99.5	Transferred entry: 1.17.98.1
+1.17.99.6	Epoxyqueuosine reductase
+1.18.1.1	Rubredoxin--NAD(+) reductase
+1.18.1.2	Ferredoxin--NADP(+) reductase
+1.18.1.3	Ferredoxin--NAD(+) reductase
+1.18.1.4	Rubredoxin--NAD(P)(+) reductase
+1.18.1.5	Putidaredoxin--NAD(+) reductase
+1.18.1.6	Adrenodoxin-NADP(+) reductase
+1.18.1.7	specific)
+1.18.1.8	Ferredoxin-NAD(+) oxidoreductase (Na(+)-transporting)
+1.18.2.1	Transferred entry: 1.18.6.1
+1.18.3.1	Transferred entry: 1.12.7.2
+1.18.6.1	Nitrogenase
+1.18.96.1	Transferred entry: 1.15.1.2
+1.18.99.1	Transferred entry: 1.12.7.2
+1.19.6.1	Nitrogenase (flavodoxin)
+1.20.1.1	Phosphonate dehydrogenase
+1.20.2.1	Arsenate reductase (cytochrome c)
+1.20.4.1	Arsenate reductase (glutaredoxin)
+1.20.4.2	Methylarsonate reductase
+1.20.4.3	Mycoredoxin
+1.20.4.4	Arsenate reductase (thioredoxin)
+1.20.9.1	Arsenate reductase (azurin)
+1.20.98.1	Transferred entry: 1.20.9.1
+1.20.99.1	Arsenate reductase (donor)
+1.21.1.1	Iodotyrosine deiodinase
+1.21.1.2	2,4-dichlorobenzoyl-CoA reductase
+1.21.3.1	Isopenicillin-N synthase
+1.21.3.2	Columbamine oxidase
+1.21.3.3	Reticuline oxidase
+1.21.3.4	Sulochrin oxidase ((+)-bisdechlorogeodin-forming)
+1.21.3.5	Sulochrin oxidase ((-)-bisdechlorogeodin-forming)
+1.21.3.6	Aureusidin synthase
+1.21.3.7	Tetrahydrocannabinolic acid synthase
+1.21.3.8	Cannabidiolic acid synthase
+1.21.3.9	Dichlorochromopyrrolate synthase
+1.21.4.1	D-proline reductase (dithiol)
+1.21.4.2	Glycine reductase
+1.21.4.3	Sarcosine reductase
+1.21.4.4	Betaine reductase
+1.21.98.1	Cyclic dehypoxanthinyl futalosine synthase
+1.21.99.1	Beta-cyclopiazonate dehydrogenase
+1.21.99.2	Transferred entry: 1.21.98.1
+1.21.99.3	Thyroxine 5-deiodinase
+1.21.99.4	Thyroxine 5'-deiodinase
+1.22.1.1	Transferred entry: 1.21.1.1
+1.23.1.1	(+)-pinoresinol reductase
+1.23.1.2	(+)-lariciresinol reductase
+1.23.1.3	(-)-pinoresinol reductase
+1.23.1.4	(-)-lariciresinol reductase
+1.23.5.1	Violaxanthin de-epoxidase
+1.97.1.1	Chlorate reductase
+1.97.1.2	Pyrogallol hydroxytransferase
+1.97.1.3	Transferred entry: 1.12.98.4
+1.97.1.4	[Formate-C-acetyltransferase]-activating enzyme
+1.97.1.5	Transferred entry: 1.20.4.1
+1.97.1.6	Transferred entry: 1.20.99.1
+1.97.1.7	Transferred entry: 1.20.4.2
+1.97.1.8	Tetrachloroethene reductive dehalogenase
+1.97.1.9	Selenate reductase
+1.97.1.10	Transferred entry: 1.21.99.4
+1.97.1.11	Transferred entry: 1.21.99.3
+1.97.1.12	Photosystem I
+1.98.1.1	Transferred entry: 1.12.7.2
+1.99.1.1	Transferred entry: 1.14.14.1
+1.99.1.2	Transferred entry: 1.14.16.1
+1.99.1.3	Deleted entry
+1.99.1.4	Deleted entry
+1.99.1.5	Transferred entry: 1.14.13.9
+1.99.1.6	Deleted entry
+1.99.1.7	Transferred entry: 1.14.15.4
+1.99.1.8	Deleted entry
+1.99.1.9	Transferred entry: 1.14.14.19
+1.99.1.10	Deleted entry
+1.99.1.11	Transferred entry: 1.14.14.16
+1.99.1.12	Deleted entry
+1.99.1.13	Transferred entry: 1.14.14.17 and 5.4.99.7
+1.99.1.14	Transferred entry: 1.13.11.27
+1.99.2.1	Transferred entry: 1.13.11.12
+1.99.2.2	Transferred entry: 1.13.11.1
+1.99.2.3	Transferred entry: 1.13.11.3
+1.99.2.4	Transferred entry: 1.13.11.4
+1.99.2.5	Transferred entry: 1.13.11.5
+1.99.2.6	Transferred entry: 1.13.99.1
+2.1.1.1	Nicotinamide N-methyltransferase
+2.1.1.2	Guanidinoacetate N-methyltransferase
+2.1.1.3	Thetin--homocysteine S-methyltransferase
+2.1.1.4	Acetylserotonin O-methyltransferase
+2.1.1.5	Betaine--homocysteine S-methyltransferase
+2.1.1.6	Catechol O-methyltransferase
+2.1.1.7	Nicotinate N-methyltransferase
+2.1.1.8	Histamine N-methyltransferase
+2.1.1.9	Thiol S-methyltransferase
+2.1.1.10	Homocysteine S-methyltransferase
+2.1.1.11	Magnesium protoporphyrin IX methyltransferase
+2.1.1.12	Methionine S-methyltransferase
+2.1.1.13	Methionine synthase
+2.1.1.14	5-methyltetrahydropteroyltriglutamate--homocysteine S-methyltransferase
+2.1.1.15	Fatty-acid O-methyltransferase
+2.1.1.16	Methylene-fatty-acyl-phospholipid synthase
+2.1.1.17	Phosphatidylethanolamine N-methyltransferase
+2.1.1.18	Polysaccharide O-methyltransferase
+2.1.1.19	Trimethylsulfonium--tetrahydrofolate N-methyltransferase
+2.1.1.20	Glycine N-methyltransferase
+2.1.1.21	Methylamine--glutamate N-methyltransferase
+2.1.1.22	Carnosine N-methyltransferase
+2.1.1.23	Transferred entry: 2.1.1.319, 2.1.1.320, 2.1.1.321 and 2.1.1.322
+2.1.1.24	Transferred entry: 2.1.1.77, 2.1.1.80 and 2.1.1.100
+2.1.1.25	Phenol O-methyltransferase
+2.1.1.26	Iodophenol O-methyltransferase
+2.1.1.27	Tyramine N-methyltransferase
+2.1.1.28	Phenylethanolamine N-methyltransferase
+2.1.1.29	Transferred entry: 2.1.1.202, 2.1.1.203 and 2.1.1.204
+2.1.1.30	Deleted entry
+2.1.1.31	Transferred entry: 2.1.1.221 and 2.1.1.228
+2.1.1.32	Transferred entry: 2.1.1.213, 2.1.1.214, 2.1.1.215 and 2.1.1.216
+2.1.1.33	tRNA (guanine(46)-N(7))-methyltransferase
+2.1.1.34	tRNA (guanosine(18)-2'-O)-methyltransferase
+2.1.1.35	tRNA (uracil(54)-C(5))-methyltransferase
+2.1.1.36	Transferred entry: 2.1.1.217, 2.1.1.218, 2.1.1.219 and 2.1.1.220
+2.1.1.37	DNA (cytosine-5-)-methyltransferase
+2.1.1.38	O-demethylpuromycin O-methyltransferase
+2.1.1.39	Inositol 3-methyltransferase
+2.1.1.40	Inositol 1-methyltransferase
+2.1.1.41	Sterol 24-C-methyltransferase
+2.1.1.42	Flavone 3'-O-methyltransferase
+2.1.1.43	Histone-lysine N-methyltransferase
+2.1.1.44	L-histidine N(alpha)-methyltransferase
+2.1.1.45	Thymidylate synthase
+2.1.1.46	Isoflavone 4'-O-methyltransferase
+2.1.1.47	Indolepyruvate C-methyltransferase
+2.1.1.48	Transferred entry: 2.1.1.181, 2.1.1.182, 2.1.1.183 and 2.1.1.184
+2.1.1.49	Amine N-methyltransferase
+2.1.1.50	Loganate O-methyltransferase
+2.1.1.51	Transferred entry: 2.1.1.187 and 2.1.1.188
+2.1.1.52	Transferred entry: 2.1.1.171, 2.1.1.172, 2.1.1.173 and 2.1.1.174
+2.1.1.53	Putrescine N-methyltransferase
+2.1.1.54	Deoxycytidylate C-methyltransferase
+2.1.1.55	tRNA (adenine-N(6)-)-methyltransferase
+2.1.1.56	mRNA (guanine-N(7)-)-methyltransferase
+2.1.1.57	Methyltransferase cap1
+2.1.1.58	Transferred entry: 2.1.1.57
+2.1.1.59	[Cytochrome c]-lysine N-methyltransferase
+2.1.1.60	Calmodulin-lysine N-methyltransferase
+2.1.1.61	tRNA (5-methylaminomethyl-2-thiouridylate)-methyltransferase
+2.1.1.62	mRNA (2'-O-methyladenosine-N(6)-)-methyltransferase
+2.1.1.63	Methylated-DNA--[protein]-cysteine S-methyltransferase
+2.1.1.64	3-demethylubiquinol 3-O-methyltransferase
+2.1.1.65	Licodione 2'-O-methyltransferase
+2.1.1.66	Transferred entry: 2.1.1.230
+2.1.1.67	Thiopurine S-methyltransferase
+2.1.1.68	Caffeate O-methyltransferase
+2.1.1.69	5-hydroxyfuranocoumarin 5-O-methyltransferase
+2.1.1.70	8-hydroxyfuranocoumarin 8-O-methyltransferase
+2.1.1.71	Phosphatidyl-N-methylethanolamine N-methyltransferase
+2.1.1.72	Site-specific DNA-methyltransferase (adenine-specific)
+2.1.1.73	Transferred entry: 2.1.1.37
+2.1.1.74	(FADH(2)-oxidizing)
+2.1.1.75	Apigenin 4'-O-methyltransferase
+2.1.1.76	Quercetin 3-O-methyltransferase
+2.1.1.77	Protein-L-isoaspartate(D-aspartate) O-methyltransferase
+2.1.1.78	Isoorientin 3'-O-methyltransferase
+2.1.1.79	Cyclopropane-fatty-acyl-phospholipid synthase
+2.1.1.80	Protein-glutamate O-methyltransferase
+2.1.1.81	Transferred entry: 2.1.1.49
+2.1.1.82	3-methylquercetin 7-O-methyltransferase
+2.1.1.83	3,7-dimethylquercetin 4'-O-methyltransferase
+2.1.1.84	Methylquercetagetin 6-O-methyltransferase
+2.1.1.85	Protein-histidine N-methyltransferase
+2.1.1.86	Tetrahydromethanopterin S-methyltransferase
+2.1.1.87	Pyridine N-methyltransferase
+2.1.1.88	8-hydroxyquercetin 8-O-methyltransferase
+2.1.1.89	Tetrahydrocolumbamine 2-O-methyltransferase
+2.1.1.90	Methanol--corrinoid protein Co-methyltransferase
+2.1.1.91	Isobutyraldoxime O-methyltransferase
+2.1.1.92	Transferred entry: 2.1.1.69
+2.1.1.93	Transferred entry: 2.1.1.70
+2.1.1.94	Tabersonine 16-O-methyltransferase
+2.1.1.95	Tocopherol O-methyltransferase
+2.1.1.96	Thioether S-methyltransferase
+2.1.1.97	3-hydroxyanthranilate 4-C-methyltransferase
+2.1.1.98	Diphthine synthase
+2.1.1.99	3-hydroxy-16-methoxy-2,3-dihydrotabersonine N-methyltransferase
+2.1.1.100	Protein-S-isoprenylcysteine O-methyltransferase
+2.1.1.101	Macrocin O-methyltransferase
+2.1.1.102	Demethylmacrocin O-methyltransferase
+2.1.1.103	Phosphoethanolamine N-methyltransferase
+2.1.1.104	Caffeoyl-CoA O-methyltransferase
+2.1.1.105	N-benzoyl-4-hydroxyanthranilate 4-O-methyltransferase
+2.1.1.106	Tryptophan 2-C-methyltransferase
+2.1.1.107	Uroporphyrinogen-III C-methyltransferase
+2.1.1.108	6-hydroxymellein O-methyltransferase
+2.1.1.109	Demethylsterigmatocystin 6-O-methyltransferase
+2.1.1.110	Sterigmatocystin 8-O-methyltransferase
+2.1.1.111	Anthranilate N-methyltransferase
+2.1.1.112	Glucuronoxylan 4-O-methyltransferase
+2.1.1.113	Site-specific DNA-methyltransferase (cytosine-N(4)-specific)
+2.1.1.114	Polyprenyldihydroxybenzoate methyltransferase
+2.1.1.115	(RS)-1-benzyl-1,2,3,4-tetrahydroisoquinoline N-methyltransferase
+2.1.1.116	3'-hydroxy-N-methyl-(S)-coclaurine 4'-O-methyltransferase
+2.1.1.117	(S)-scoulerine 9-O-methyltransferase
+2.1.1.118	Columbamine O-methyltransferase
+2.1.1.119	10-hydroxydihydrosanguinarine 10-O-methyltransferase
+2.1.1.120	12-hydroxydihydrochelirubine 12-O-methyltransferase
+2.1.1.121	6-O-methylnorlaudanosoline 5'-O-methyltransferase
+2.1.1.122	(S)-tetrahydroprotoberberine N-methyltransferase
+2.1.1.123	[Cytochrome c]-methionine S-methyltransferase
+2.1.1.124	Transferred entry: 2.1.1.319, 2.1.1.320, 2.1.1.321 and 2.1.1.322
+2.1.1.125	Transferred entry: 2.1.1.319, 2.1.1.320, 2.1.1.321 and 2.1.1.322
+2.1.1.126	Transferred entry: 2.1.1.319, 2.1.1.320, 2.1.1.321 and 2.1.1.322
+2.1.1.127	[Ribulose-bisphosphate carboxylase]-lysine N-methyltransferase
+2.1.1.128	(RS)-norcoclaurine 6-O-methyltransferase
+2.1.1.129	Inositol 4-methyltransferase
+2.1.1.130	Precorrin-2 C(20)-methyltransferase
+2.1.1.131	Precorrin-3B C(17)-methyltransferase
+2.1.1.132	Precorrin-6B C(5,15)-methyltransferase (decarboxylating)
+2.1.1.133	Precorrin-4 C(11)-methyltransferase
+2.1.1.134	Transferred entry: 2.1.1.129
+2.1.1.135	Transferred entry: 1.16.1.8
+2.1.1.136	Chlorophenol O-methyltransferase
+2.1.1.137	Arsenite methyltransferase
+2.1.1.138	Deleted entry
+2.1.1.139	3'-demethylstaurosporine O-methyltransferase
+2.1.1.140	(S)-coclaurine-N-methyltransferase
+2.1.1.141	Jasmonate O-methyltransferase
+2.1.1.142	Cycloartenol 24-C-methyltransferase
+2.1.1.143	24-methylenesterol C-methyltransferase
+2.1.1.144	Trans-aconitate 2-methyltransferase
+2.1.1.145	Trans-aconitate 3-methyltransferase
+2.1.1.146	(Iso)eugenol O-methyltransferase
+2.1.1.147	Corydaline synthase
+2.1.1.148	Thymidylate synthase (FAD)
+2.1.1.149	Transferred entry: 2.1.1.267
+2.1.1.150	Isoflavone 7-O-methyltransferase
+2.1.1.151	Cobalt-factor II C(20)-methyltransferase
+2.1.1.152	Precorrin-6A synthase (deacetylating)
+2.1.1.153	Vitexin 2''-O-rhamnoside 7-O-methyltransferase
+2.1.1.154	Isoliquiritigenin 2'-O-methyltransferase
+2.1.1.155	Kaempferol 4'-O-methyltransferase
+2.1.1.156	Glycine/sarcosine N-methyltransferase
+2.1.1.157	Sarcosine/dimethylglycine N-methyltransferase
+2.1.1.158	7-methylxanthosine synthase
+2.1.1.159	Theobromine synthase
+2.1.1.160	Caffeine synthase
+2.1.1.161	Dimethylglycine N-methyltransferase
+2.1.1.162	Glycine/sarcosine/dimethylglycine N-methyltransferase
+2.1.1.163	Demethylmenaquinone methyltransferase
+2.1.1.164	Demethylrebeccamycin-D-glucose O-methyltransferase
+2.1.1.165	Methyl halide transferase
+2.1.1.166	23S rRNA (uridine(2552)-2'-O)-methyltransferase
+2.1.1.167	27S pre-rRNA (guanosine(2922)-2'-O)-methyltransferase
+2.1.1.168	21S rRNA (uridine(2791)-2'-O)-methyltransferase
+2.1.1.169	Tricetin 3',4',5'-O-trimethyltransferase
+2.1.1.170	16S rRNA (guanine(527)-N(7))-methyltransferase
+2.1.1.171	16S rRNA (guanine(966)-N(2))-methyltransferase
+2.1.1.172	16S rRNA (guanine(1207)-N(2))-methyltransferase
+2.1.1.173	23S rRNA (guanine(2445)-N(2))-methyltransferase
+2.1.1.174	23S rRNA (guanine(1835)-N(2))-methyltransferase
+2.1.1.175	Tricin synthase
+2.1.1.176	16S rRNA (cytosine(967)-C(5))-methyltransferase
+2.1.1.177	23S rRNA (pseudouridine(1915)-N(3))-methyltransferase
+2.1.1.178	16S rRNA (cytosine(1407)-C(5))-methyltransferase
+2.1.1.179	16S rRNA (guanine(1405)-N(7))-methyltransferase
+2.1.1.180	16S rRNA (adenine(1408)-N(1))-methyltransferase
+2.1.1.181	23S rRNA (adenine(1618)-N(6))-methyltransferase
+2.1.1.182	16S rRNA (adenine(1518)-N(6)/adenine(1519)-N(6))-dimethyltransferase
+2.1.1.183	18S rRNA (adenine(1779)-N(6)/adenine(1780)-N(6))-dimethyltransferase
+2.1.1.184	23S rRNA (adenine(2085)-N(6))-dimethyltransferase
+2.1.1.185	23S rRNA (guanosine(2251)-2'-O)-methyltransferase
+2.1.1.186	23S rRNA (cytidine(2498)-2'-O)-methyltransferase
+2.1.1.187	23S rRNA (guanine(745)-N(1))-methyltransferase
+2.1.1.188	23S rRNA (guanine(748)-N(1))-methyltransferase
+2.1.1.189	23S rRNA (uracil(747)-C(5))-methyltransferase
+2.1.1.190	23S rRNA (uracil(1939)-C(5))-methyltransferase
+2.1.1.191	23S rRNA (cytosine(1962)-C(5))-methyltransferase
+2.1.1.192	23S rRNA (adenine(2503)-C(2))-methyltransferase
+2.1.1.193	16S rRNA (uracil(1498)-N(3))-methyltransferase
+2.1.1.194	Deleted entry
+2.1.1.195	Cobalt-precorrin-5B (C(1))-methyltransferase
+2.1.1.196	Cobalt-precorrin-6B (C(15))-methyltransferase (decarboxylating)
+2.1.1.197	Malonyl-[acyl-carrier protein] O-methyltransferase
+2.1.1.198	16S rRNA (cytidine(1402)-2'-O)-methyltransferase
+2.1.1.199	16S rRNA (cytosine(1402)-N(4))-methyltransferase
+2.1.1.200	tRNA (cytidine(32)/uridine(32)-2'-O)-methyltransferase
+2.1.1.201	2-methoxy-6-polyprenyl-1,4-benzoquinol methylase
+2.1.1.202	Multisite-specific tRNA:(cytosine-C(5))-methyltransferase
+2.1.1.203	tRNA (cytosine(34)-C(5))-methyltransferase
+2.1.1.204	tRNA (cytosine(38)-C(5))-methyltransferase
+2.1.1.205	tRNA (cytidine(32)/guanosine(34)-2'-O)-methyltransferase
+2.1.1.206	tRNA (cytidine(56)-2'-O)-methyltransferase
+2.1.1.207	tRNA (cytidine(34)-2'-O)-methyltransferase
+2.1.1.208	23S rRNA (uridine(2479)-2'-O)-methyltransferase
+2.1.1.209	23S rRNA (guanine(2535)-N(1))-methyltransferase
+2.1.1.210	Demethylspheroidene O-methyltransferase
+2.1.1.211	tRNA(Ser) (uridine(44)-2'-O)-methyltransferase
+2.1.1.212	2,7,4'-trihydroxyisoflavanone 4'-O-methyltransferase
+2.1.1.213	tRNA (guanine(10)-N(2))-dimethyltransferase
+2.1.1.214	tRNA (guanine(10)-N(2))-methyltransferase
+2.1.1.215	tRNA (guanine(26)-N(2)/guanine(27)-N(2))-dimethyltransferase
+2.1.1.216	tRNA (guanine(26)-N(2))-dimethyltransferase
+2.1.1.217	tRNA (adenine(22)-N(1))-methyltransferase
+2.1.1.218	tRNA (adenine(9)-N(1))-methyltransferase
+2.1.1.219	tRNA (adenine(57)-N(1)/adenine(58)-N(1))-methyltransferase
+2.1.1.220	tRNA (adenine(58)-N(1))-methyltransferase
+2.1.1.221	tRNA (guanine(9)-N(1))-methyltransferase
+2.1.1.222	2-polyprenyl-6-hydroxyphenol methylase
+2.1.1.223	tRNA(1)(Val) (adenine(37)-N(6))-methyltransferase
+2.1.1.224	23S rRNA (adenine(2503)-C(8))-methyltransferase
+2.1.1.225	tRNA:m(4)X modification enzyme
+2.1.1.226	23S rRNA (cytidine(1920)-2'-O)-methyltransferase
+2.1.1.227	16S rRNA (cytidine(1409)-2'-O)-methyltransferase
+2.1.1.228	tRNA (guanine(37)-N(1))-methyltransferase
+2.1.1.229	tRNA (carboxymethyluridine(34)-5-O)-methyltransferase
+2.1.1.230	23S rRNA (adenosine(1067)-2'-O)-methyltransferase
+2.1.1.231	Flavonoid 4'-O-methyltransferase
+2.1.1.232	Naringenin 7-O-methyltransferase
+2.1.1.233	[Phosphatase 2A protein]-leucine-carboxy methyltransferase
+2.1.1.234	N,N-dimethyltransferase
+2.1.1.235	dTDP-3-amino-3,6-dideoxy-alpha-D-glucopyranose N,N-dimethyltransferase
+2.1.1.236	dTDP-3-amino-3,6-dideoxy-alpha-D-galactopyranose N,N-dimethyltransferase
+2.1.1.237	Mycinamicin III 3''-O-methyltransferase
+2.1.1.238	Mycinamicin VI 2''-O-methyltransferase
+2.1.1.239	L-olivosyl-oleandolide 3-O-methyltransferase
+2.1.1.240	Trans-resveratrol di-O-methyltransferase
+2.1.1.241	2,4,7-trihydroxy-1,4-benzoxazin-3-one-glucoside 7-O-methyltransferase
+2.1.1.242	16S rRNA (guanine(1516)-N(2))-methyltransferase
+2.1.1.243	2-ketoarginine methyltransferase
+2.1.1.244	Protein N-terminal methyltransferase
+2.1.1.245	Co-methyltransferase
+2.1.1.246	methyltransferase
+2.1.1.247	methyltransferase
+2.1.1.248	[Methylamine--corrinoid protein] Co-methyltransferase
+2.1.1.249	[Dimethylamine--corrinoid protein] Co-methyltransferase
+2.1.1.250	[Trimethylamine--corrinoid protein] Co-methyltransferase
+2.1.1.251	Methylated-thiol--coenzyme M methyltransferase
+2.1.1.252	Tetramethylammonium--corrinoid protein Co-methyltransferase
+2.1.1.253	M methyltransferase
+2.1.1.254	Erythromycin 3''-O-methyltransferase
+2.1.1.255	Geranyl diphosphate 2-C-methyltransferase
+2.1.1.256	tRNA (guanine(6)-N(2))-methyltransferase
+2.1.1.257	tRNA (pseudouridine(54)-N(1))-methyltransferase
+2.1.1.258	Co-methyltransferase
+2.1.1.259	[Fructose-bisphosphate aldolase]-lysine N-methyltransferase
+2.1.1.260	rRNA small subunit pseudouridine methyltransferase Nep1
+2.1.1.261	4-dimethylallyltryptophan N-methyltransferase
+2.1.1.262	Squalene methyltransferase
+2.1.1.263	Botryococcene C-methyltransferase
+2.1.1.264	23S rRNA (guanine(2069)-N(7))-methyltransferase
+2.1.1.265	Tellurite methyltransferase
+2.1.1.266	23S rRNA (adenine(2030)-N(6))-methyltransferase
+2.1.1.267	Flavonoid 3',5'-methyltransferase
+2.1.1.268	tRNA(Thr) (cytosine(32)-N(3))-methyltransferase
+2.1.1.269	Dimethylsulfoniopropionate demethylase
+2.1.1.270	(+)-6a-hydroxymaackiain 3-O-methyltransferase
+2.1.1.271	Cobalt-precorrin-4 methyltransferase
+2.1.1.272	Cobalt-factor III methyltransferase
+2.1.1.273	Benzoate O-methyltransferase
+2.1.1.274	Salicylate carboxymethyltransferase
+2.1.1.275	Gibberellin A(9) O-methyltransferase
+2.1.1.276	Gibberellin A(4) carboxyl methyltransferase
+2.1.1.277	Anthranilate O-methyltransferase
+2.1.1.278	Indole-3-acetate O-methyltransferase
+2.1.1.279	Trans-anol O-methyltransferase
+2.1.1.280	Selenocysteine Se-methyltransferase
+2.1.1.281	Phenylpyruvate C(3)-methyltransferase
+2.1.1.282	methyltransferase
+2.1.1.283	Emodin O-methyltransferase
+2.1.1.284	8-demethylnovobiocic acid C(8)-methyltransferase
+2.1.1.285	Demethyldecarbamoylnovobiocin O-methyltransferase
+2.1.1.286	25S rRNA (adenine(2142)-N(1))-methyltransferase
+2.1.1.287	25S rRNA (adenine(645)-N(1))-methyltransferase
+2.1.1.288	Aklanonic acid methyltransferase
+2.1.1.289	Cobalt-precorrin-7 (C(5))-methyltransferase
+2.1.1.290	tRNA(Phe) (7-(3-amino-3-carboxypropyl)wyosine(37)-O)-methyltransferase
+2.1.1.291	(R,S)-reticuline 7-O-methyltransferase
+2.1.1.292	Carminomycin 4-O-methyltransferase
+2.1.1.293	6-hydroxytryprostatin B O-methyltransferase
+2.1.1.294	3-phospho-methyltransferase
+2.1.1.295	2-methyl-6-phytyl-1,4-hydroquinone methyltransferase
+2.1.1.296	Methyltransferase cap2
+2.1.1.297	Peptide chain release factor N(5)-glutamine methyltransferase
+2.1.1.298	Ribosomal protein L3 N(5)-glutamine methyltransferase
+2.1.1.299	Protein N-terminal monomethyltransferase
+2.1.1.300	Pavine N-methyltransferase
+2.1.1.301	Cypemycin N-terminal methyltransferase
+2.1.1.302	3-hydroxy-5-methyl-1-naphthoate 3-O-methyltransferase
+2.1.1.303	2,7-dihydroxy-5-methyl-1-naphthoate 7-O-methyltransferase
+2.1.1.304	L-tyrosine C(3)-methyltransferase
+2.1.1.305	8-demethyl-8-alpha-L-rhamnosyl tetracenomycin-C 2'-O-methyltransferase
+2.1.1.306	methyltransferase
+2.1.1.307	methyltransferase
+2.1.1.308	2-hydroxyethylphosphonate methyltransferase
+2.1.1.309	18S rRNA (guanine(1575)-N(7))-methyltransferase
+2.1.1.310	25S rRNA (cytosine(2870)-C(5))-methyltransferase
+2.1.1.311	25S rRNA (cytosine(2278)-C(5))-methyltransferase
+2.1.1.312	25S rRNA (uracil(2843)-N(3))-methyltransferase
+2.1.1.313	25S rRNA (uracil(2634)-N(3))-methyltransferase
+2.1.1.314	Diphthine methyl ester synthase
+2.1.1.315	27-O-demethylrifamycin SV methyltransferase
+2.1.1.316	Mitomycin 6-O-methyltransferase
+2.1.1.317	Sphingolipid C(9)-methyltransferase
+2.1.1.318	[Trehalose-6-phosphate synthase]-L-cysteine S-methyltransferase
+2.1.1.319	Type I protein arginine methyltransferase
+2.1.1.320	Type II protein arginine methyltransferase
+2.1.1.321	Type III protein arginine methyltransferase
+2.1.1.322	Type IV protein arginine methyltransferase
+2.1.2.1	Glycine hydroxymethyltransferase
+2.1.2.2	Phosphoribosylglycinamide formyltransferase
+2.1.2.3	Phosphoribosylaminoimidazolecarboxamide formyltransferase
+2.1.2.4	Glycine formimidoyltransferase
+2.1.2.5	Glutamate formimidoyltransferase
+2.1.2.6	Transferred entry: 2.1.2.5
+2.1.2.7	D-alanine 2-hydroxymethyltransferase
+2.1.2.8	Deoxycytidylate 5-hydroxymethyltransferase
+2.1.2.9	Methionyl-tRNA formyltransferase
+2.1.2.10	Aminomethyltransferase
+2.1.2.11	3-methyl-2-oxobutanoate hydroxymethyltransferase
+2.1.2.12	Transferred entry: 2.1.1.74
+2.1.2.13	UDP-4-amino-4-deoxy-L-arabinose formyltransferase
+2.1.3.1	Methylmalonyl-CoA carboxytransferase
+2.1.3.2	Aspartate carbamoyltransferase
+2.1.3.3	Ornithine carbamoyltransferase
+2.1.3.4	Deleted entry
+2.1.3.5	Oxamate carbamoyltransferase
+2.1.3.6	Putrescine carbamoyltransferase
+2.1.3.7	3-hydroxymethylcephem carbamoyltransferase
+2.1.3.8	Lysine carbamoyltransferase
+2.1.3.9	N-acetylornithine carbamoyltransferase
+2.1.3.10	Malonyl-S-ACP:biotin-protein carboxyltransferase
+2.1.3.11	N-succinylornithine carbamoyltransferase
+2.1.3.12	Decarbamoylnovobiocin carbamoyltransferase
+2.1.3.13	Transferred entry: 6.1.2.2
+2.1.3.14	Transferred entry: 6.1.2.2
+2.1.4.1	Glycine amidinotransferase
+2.1.4.2	Scyllo-inosamine-4-phosphate amidinotransferase
+2.2.1.1	Transketolase
+2.2.1.2	Transaldolase
+2.2.1.3	Formaldehyde transketolase
+2.2.1.4	Acetoin--ribose-5-phosphate transaldolase
+2.2.1.5	2-hydroxy-3-oxoadipate synthase
+2.2.1.6	Acetolactate synthase
+2.2.1.7	1-deoxy-D-xylulose-5-phosphate synthase
+2.2.1.8	Fluorothreonine transaldolase
+2.2.1.9	synthase
+2.2.1.10	2-amino-3,7-dideoxy-D-threo-hept-6-ulosonate synthase
+2.2.1.11	6-deoxy-5-ketofructose 1-phosphate synthase
+2.2.1.12	3-acetyloctanal synthase
+2.3.1.1	Amino-acid N-acetyltransferase
+2.3.1.2	Imidazole N-acetyltransferase
+2.3.1.3	Glucosamine N-acetyltransferase
+2.3.1.4	Glucosamine-phosphate N-acetyltransferase
+2.3.1.5	Arylamine N-acetyltransferase
+2.3.1.6	Choline O-acetyltransferase
+2.3.1.7	Carnitine O-acetyltransferase
+2.3.1.8	Phosphate acetyltransferase
+2.3.1.9	Acetyl-CoA C-acetyltransferase
+2.3.1.10	Hydrogen-sulfide S-acetyltransferase
+2.3.1.11	Thioethanolamine S-acetyltransferase
+2.3.1.12	Dihydrolipoyllysine-residue acetyltransferase
+2.3.1.13	Glycine N-acyltransferase
+2.3.1.14	Glutamine N-phenylacetyltransferase
+2.3.1.15	Glycerol-3-phosphate 1-O-acyltransferase
+2.3.1.16	Acetyl-CoA C-acyltransferase
+2.3.1.17	Aspartate N-acetyltransferase
+2.3.1.18	Galactoside O-acetyltransferase
+2.3.1.19	Phosphate butyryltransferase
+2.3.1.20	Diacylglycerol O-acyltransferase
+2.3.1.21	Carnitine O-palmitoyltransferase
+2.3.1.22	2-acylglycerol O-acyltransferase
+2.3.1.23	1-acylglycerophosphocholine O-acyltransferase
+2.3.1.24	Sphingosine N-acyltransferase
+2.3.1.25	Plasmalogen synthase
+2.3.1.26	Sterol O-acyltransferase
+2.3.1.27	Cortisol O-acetyltransferase
+2.3.1.28	Chloramphenicol O-acetyltransferase
+2.3.1.29	Glycine C-acetyltransferase
+2.3.1.30	Serine O-acetyltransferase
+2.3.1.31	Homoserine O-acetyltransferase
+2.3.1.32	Lysine N-acetyltransferase
+2.3.1.33	Histidine N-acetyltransferase
+2.3.1.34	D-tryptophan N-acetyltransferase
+2.3.1.35	Glutamate N-acetyltransferase
+2.3.1.36	D-amino-acid N-acetyltransferase
+2.3.1.37	5-aminolevulinate synthase
+2.3.1.38	[Acyl-carrier-protein] S-acetyltransferase
+2.3.1.39	[Acyl-carrier-protein] S-malonyltransferase
+2.3.1.40	Acyl-[acyl-carrier-protein]--phospholipid O-acyltransferase
+2.3.1.41	Beta-ketoacyl-[acyl-carrier-protein] synthase I
+2.3.1.42	Glycerone-phosphate O-acyltransferase
+2.3.1.43	Phosphatidylcholine--sterol O-acyltransferase
+2.3.1.44	N-acetylneuraminate 4-O-acetyltransferase
+2.3.1.45	N-acetylneuraminate 7-O(or 9-O)-acetyltransferase
+2.3.1.46	Homoserine O-succinyltransferase
+2.3.1.47	8-amino-7-oxononanoate synthase
+2.3.1.48	Histone acetyltransferase
+2.3.1.49	Deacetyl-[citrate-(pro-3S)-lyase] S-acetyltransferase
+2.3.1.50	Serine C-palmitoyltransferase
+2.3.1.51	1-acylglycerol-3-phosphate O-acyltransferase
+2.3.1.52	2-acylglycerol-3-phosphate O-acyltransferase
+2.3.1.53	Phenylalanine N-acetyltransferase
+2.3.1.54	Formate C-acetyltransferase
+2.3.1.55	Transferred entry: 2.3.1.82
+2.3.1.56	Aromatic-hydroxylamine O-acetyltransferase
+2.3.1.57	Diamine N-acetyltransferase
+2.3.1.58	2,3-diaminopropionate N-oxalyltransferase
+2.3.1.59	Gentamicin 2'-N-acetyltransferase
+2.3.1.60	Gentamicin 3-N-acetyltransferase
+2.3.1.61	Dihydrolipoyllysine-residue succinyltransferase
+2.3.1.62	2-acylglycerophosphocholine O-acyltransferase
+2.3.1.63	1-alkylglycerophosphocholine O-acyltransferase
+2.3.1.64	Agmatine N(4)-coumaroyltransferase
+2.3.1.65	Bile acid-CoA:amino acid N-acyltransferase
+2.3.1.66	Leucine N-acetyltransferase
+2.3.1.67	1-alkylglycerophosphocholine O-acetyltransferase
+2.3.1.68	Glutamine N-acyltransferase
+2.3.1.69	Monoterpenol O-acetyltransferase
+2.3.1.70	Deleted entry
+2.3.1.71	Glycine N-benzoyltransferase
+2.3.1.72	Indoleacetylglucose--inositol O-acyltransferase
+2.3.1.73	Diacylglycerol--sterol O-acyltransferase
+2.3.1.74	Naringenin-chalcone synthase
+2.3.1.75	Long-chain-alcohol O-fatty-acyltransferase
+2.3.1.76	Retinol O-fatty-acyltransferase
+2.3.1.77	Triacylglycerol--sterol O-acyltransferase
+2.3.1.78	Heparan-alpha-glucosaminide N-acetyltransferase
+2.3.1.79	Maltose O-acetyltransferase
+2.3.1.80	Cysteine-S-conjugate N-acetyltransferase
+2.3.1.81	Aminoglycoside N(3)-acetyltransferase
+2.3.1.82	Aminoglycoside 6'-N-acetyltransferase
+2.3.1.83	Phosphatidylcholine--dolichol O-acyltransferase
+2.3.1.84	Alcohol O-acetyltransferase
+2.3.1.85	Fatty-acid synthase
+2.3.1.86	Fatty-acyl-CoA synthase
+2.3.1.87	Aralkylamine N-acetyltransferase
+2.3.1.88	Peptide alpha-N-acetyltransferase
+2.3.1.89	Tetrahydrodipicolinate N-acetyltransferase
+2.3.1.90	Beta-glucogallin O-galloyltransferase
+2.3.1.91	Sinapoylglucose--choline O-sinapoyltransferase
+2.3.1.92	Sinapoylglucose--malate O-sinapoyltransferase
+2.3.1.93	13-hydroxylupanine O-tigloyltransferase
+2.3.1.94	6-deoxyerythronolide-B synthase
+2.3.1.95	Trihydroxystilbene synthase
+2.3.1.96	Glycoprotein N-palmitoyltransferase
+2.3.1.97	Glycylpeptide N-tetradecanoyltransferase
+2.3.1.98	Chlorogenate--glucarate O-hydroxycinnamoyltransferase
+2.3.1.99	Quinate O-hydroxycinnamoyltransferase
+2.3.1.100	[Myelin-proteolipid] O-palmitoyltransferase
+2.3.1.101	Formylmethanofuran--tetrahydromethanopterin N-formyltransferase
+2.3.1.102	N(6)-hydroxylysine O-acetyltransferase
+2.3.1.103	Sinapoylglucose--sinapoylglucose O-sinapoyltransferase
+2.3.1.104	Transferred entry: 2.3.1.25
+2.3.1.105	Alkylglycerophosphate 2-O-acetyltransferase
+2.3.1.106	Tartronate O-hydroxycinnamoyltransferase
+2.3.1.107	Deacetylvindoline O-acetyltransferase
+2.3.1.108	Alpha-tubulin N-acetyltransferase
+2.3.1.109	Arginine N-succinyltransferase
+2.3.1.110	Tyramine N-feruloyltransferase
+2.3.1.111	Mycocerosate synthase
+2.3.1.112	D-tryptophan N-malonyltransferase
+2.3.1.113	Anthranilate N-malonyltransferase
+2.3.1.114	3,4-dichloroaniline N-malonyltransferase
+2.3.1.115	Isoflavone-7-O-beta-glucoside 6''-O-malonyltransferase
+2.3.1.116	Flavonol-3-O-beta-glucoside O-malonyltransferase
+2.3.1.117	2,3,4,5-tetrahydropyridine-2,6-dicarboxylate N-succinyltransferase
+2.3.1.118	N-hydroxyarylamine O-acetyltransferase
+2.3.1.119	Transferred entry: 1.1.1.330, 1.3.1.93, 2.3.1.199 and 4.2.1.134
+2.3.1.120	Deleted entry
+2.3.1.121	1-alkenylglycerophosphoethanolamine O-acyltransferase
+2.3.1.122	Trehalose O-mycolyltransferase
+2.3.1.123	Dolichol O-acyltransferase
+2.3.1.124	Deleted entry
+2.3.1.125	1-alkyl-2-acetylglycerol O-acyltransferase
+2.3.1.126	Isocitrate O-dihydroxycinnamoyltransferase
+2.3.1.127	Ornithine N-benzoyltransferase
+2.3.1.128	Ribosomal-protein-alanine N-acetyltransferase
+2.3.1.129	Acyl-[acyl-carrier-protein]--UDP-N-acetylglucosamine O-acyltransferase
+2.3.1.130	Galactarate O-hydroxycinnamoyltransferase
+2.3.1.131	Glucarate O-hydroxycinnamoyltransferase
+2.3.1.132	Glucarolactone O-hydroxycinnamoyltransferase
+2.3.1.133	Shikimate O-hydroxycinnamoyltransferase
+2.3.1.134	Galactolipid O-acyltransferase
+2.3.1.135	Phosphatidylcholine--retinol O-acyltransferase
+2.3.1.136	Polysialic-acid O-acetyltransferase
+2.3.1.137	Carnitine O-octanoyltransferase
+2.3.1.138	Putrescine N-hydroxycinnamoyltransferase
+2.3.1.139	Ecdysone O-acyltransferase
+2.3.1.140	Rosmarinate synthase
+2.3.1.141	Galactosylacylglycerol O-acyltransferase
+2.3.1.142	Glycoprotein O-fatty-acyltransferase
+2.3.1.143	Beta-glucogallin--tetrakisgalloylglucose O-galloyltransferase
+2.3.1.144	Anthranilate N-benzoyltransferase
+2.3.1.145	Piperidine N-piperoyltransferase
+2.3.1.146	Pinosylvin synthase
+2.3.1.147	Glycerophospholipid arachidonoyl-transferase (CoA-independent)
+2.3.1.148	Glycerophospholipid acyltransferase (CoA-dependent)
+2.3.1.149	Platelet-activating factor acetyltransferase
+2.3.1.150	Salutaridinol 7-O-acetyltransferase
+2.3.1.151	2,3',4,6-tetrahydroxybenzophenone synthase
+2.3.1.152	Alcohol O-cinnamoyltransferase
+2.3.1.153	Anthocyanin 5-(6'''-hydroxycinnamoyltransferase)
+2.3.1.154	Propionyl-CoA C(2)-trimethyltridecanoyltransferase
+2.3.1.155	Acetyl-CoA C-myristoyltransferase
+2.3.1.156	Phloroisovalerophenone synthase
+2.3.1.157	Glucosamine-1-phosphate N-acetyltransferase
+2.3.1.158	Phospholipid:diacylglycerol acyltransferase
+2.3.1.159	Acridone synthase
+2.3.1.160	Vinorine synthase
+2.3.1.161	Lovastatin nonaketide synthase
+2.3.1.162	Taxadien-5-alpha-ol O-acetyltransferase
+2.3.1.163	10-hydroxytaxane O-acetyltransferase
+2.3.1.164	Isopenicillin-N N-acyltransferase
+2.3.1.165	6-methylsalicylic acid synthase
+2.3.1.166	2-alpha-hydroxytaxane 2-O-benzoyltransferase
+2.3.1.167	10-deacetylbaccatin III 10-O-acetyltransferase
+2.3.1.168	Dihydrolipoyllysine-residue (2-methylpropanoyl)transferase
+2.3.1.169	CO-methylating acetyl-CoA synthase
+2.3.1.170	6'-deoxychalcone synthase
+2.3.1.171	Anthocyanin 6''-O-malonyltransferase
+2.3.1.172	Anthocyanin 5-O-glucoside 6'''-O-malonyltransferase
+2.3.1.173	Flavonol-3-O-triglucoside O-coumaroyltransferase
+2.3.1.174	3-oxoadipyl-CoA thiolase
+2.3.1.175	Deacetylcephalosporin-C acetyltransferase
+2.3.1.176	Propanoyl-CoA C-acyltransferase
+2.3.1.177	3,5-dihydroxybiphenyl synthase
+2.3.1.178	Diaminobutyrate acetyltransferase
+2.3.1.179	Beta-ketoacyl-[acyl-carrier-protein] synthase II
+2.3.1.180	Beta-ketoacyl-[acyl-carrier-protein] synthase III
+2.3.1.181	Lipoyl(octanoyl) transferase
+2.3.1.182	(R)-citramalate synthase
+2.3.1.183	Phosphinothricin acetyltransferase
+2.3.1.184	Acyl-homoserine-lactone synthase
+2.3.1.185	Tropine acyltransferase
+2.3.1.186	Pseudotropine acyltransferase
+2.3.1.187	Acetyl-S-ACP:malonate ACP transferase
+2.3.1.188	Omega-hydroxypalmitate O-feruloyl transferase
+2.3.1.189	Mycothiol synthase
+2.3.1.190	Acetoin dehydrogenase
+2.3.1.191	UDP-3-O-(3-hydroxymyristoyl)glucosamine N-acyltransferase
+2.3.1.192	Glycine N-phenylacetyltransferase
+2.3.1.193	tRNA(Met) cytidine acetyltransferase
+2.3.1.194	Acetoacetyl-CoA synthase
+2.3.1.195	(Z)-3-hexen-1-ol acetyltransferase
+2.3.1.196	Benzyl alcohol O-benzoyltransferase
+2.3.1.197	dTDP-3-amino-3,6-dideoxy-alpha-D-galactopyranose 3-N-acetyltransferase
+2.3.1.198	Glycerol-3-phosphate 2-O-acyltransferase
+2.3.1.199	Very-long-chain 3-oxoacyl-CoA synthase
+2.3.1.200	Lipoyl amidotransferase
+2.3.1.201	UDP-2-acetamido-3-amino-2,3-dideoxy-glucuronate N-acetyltransferase
+2.3.1.202	UDP-4-amino-4,6-dideoxy-N-acetyl-beta-L-altrosamine N-acetyltransferase
+2.3.1.203	UDP-N-acetylbacillosamine N-acetyltransferase
+2.3.1.204	Octanoyl-[GcvH]:protein N-octanoyltransferase
+2.3.1.205	Fumigaclavine B O-acetyltransferase
+2.3.1.206	3,5,7-trioxododecanoyl-CoA synthase
+2.3.1.207	Beta-ketodecanoyl-[acyl-carrier-protein] synthase
+2.3.1.208	4-hydroxycoumarin synthase
+2.3.1.209	dTDP-4-amino-4,6-dideoxy-D-glucose acyltransferase
+2.3.1.210	dTDP-4-amino-4,6-dideoxy-D-galactose acyltransferase
+2.3.1.211	Bisdemethoxycurcumin synthase
+2.3.1.212	Benzalacetone synthase
+2.3.1.213	hydroxycinnamoyltransferase
+2.3.1.214	4'''-malonyltransferase
+2.3.1.215	Anthocyanidin 3-O-glucoside 6''-O-acyltransferase
+2.3.1.216	5,7-dihydroxy-2-methylchromone synthase
+2.3.1.217	Curcumin synthase
+2.3.1.218	Phenylpropanoylacetyl-CoA synthase
+2.3.1.219	Demethoxycurcumin synthase
+2.3.1.220	2,4,6-trihydroxybenzophenone synthase
+2.3.1.221	Noranthrone synthase
+2.3.1.222	Phosphate propanoyltransferase
+2.3.1.223	3-oxo-5,6-didehydrosuberyl-CoA thiolase
+2.3.1.224	Acetyl-CoA-benzylalcohol acetyltransferase
+2.3.1.225	Protein S-acyltransferase
+2.3.1.226	Carboxymethylproline synthase
+2.3.1.227	GDP-perosamine N-acetyltransferase
+2.3.1.228	Isovaleryl-homoserine lactone synthase
+2.3.1.229	4-coumaroyl-homoserine lactone synthase
+2.3.1.230	2-heptyl-4(1H)-quinolone synthase
+2.3.1.231	methoxycarbonyltransferase
+2.3.1.232	Methanol O-anthraniloyltransferase
+2.3.1.233	1,3,6,8-tetrahydroxynaphthalene synthase
+2.3.1.234	N(6)-L-threonylcarbamoyladenine synthase
+2.3.1.235	Tetracenomycin F2 synthase
+2.3.1.236	5-methylnaphthoic acid synthase
+2.3.1.237	Neocarzinostatin naphthoate synthase
+2.3.1.238	Monacolin J acid methylbutanoate transferase
+2.3.1.239	10-deoxymethynolide syntase
+2.3.1.240	Narbonolide synthase
+2.3.1.241	Kdo(2)-lipid IV(A) lauroyltransferase
+2.3.1.242	Kdo(2)-lipid IV(A) palmitoleoyltransferase
+2.3.1.243	Lauroyl-Kdo(2)-lipid IV(A) myristoyltransferase
+2.3.1.244	2-methylbutanoate polyketide synthase
+2.3.1.245	3-hydroxy-5-phosphonooxypentane-2,4-dione thiolase
+2.3.1.246	3,5-dihydroxyphenylacetyl-CoA synthase
+2.3.1.247	3-keto-5-aminohexanoate cleavage enzyme
+2.3.1.248	Spermidine disinapoyl transferase
+2.3.1.249	Spermidine dicoumaroyl transferase
+2.3.1.250	[Wnt protein] O-palmitoleoyl transferase
+2.3.1.251	Lipid IV(A) palmitoyltransferase
+2.3.2.1	D-glutamyltransferase
+2.3.2.2	Gamma-glutamyltransferase
+2.3.2.3	Lysyltransferase
+2.3.2.4	Gamma-glutamylcyclotransferase
+2.3.2.5	Glutaminyl-peptide cyclotransferase
+2.3.2.6	Leucyltransferase
+2.3.2.7	Aspartyltransferase
+2.3.2.8	Arginyltransferase
+2.3.2.9	Agaritine gamma-glutamyltransferase
+2.3.2.10	UDP-N-acetylmuramoylpentapeptide-lysine N(6)-alanyltransferase
+2.3.2.11	Alanylphosphatidylglycerol synthase
+2.3.2.12	Peptidyltransferase
+2.3.2.13	Protein-glutamine gamma-glutamyltransferase
+2.3.2.14	D-alanine gamma-glutamyltransferase
+2.3.2.15	Glutathione gamma-glutamylcysteinyltransferase
+2.3.2.16	Lipid II:glycine glycyltransferase
+2.3.2.17	glycyltransferase
+2.3.2.18	glycyltransferase
+2.3.2.19	transferase
+2.3.2.20	Cyclo(L-leucyl-L-phenylalanyl) synthase
+2.3.2.21	Cyclo(L-tyrosyl-L-tyrosyl) synthase
+2.3.2.22	Cyclo(L-leucyl-L-leucyl) synthase
+2.3.2.23	E2 ubiquitin-conjugating enzyme
+2.3.2.24	(E3-independent) E2 ubiquitin-conjugating enzyme
+2.3.2.25	N-terminal E2 ubiquitin-conjugating enzyme
+2.3.2.26	HECT-type E3 ubiquitin transferase
+2.3.2.27	RING-type E3 ubiquitin transferase
+2.3.2.28	L-allo-isoleucyltransferase
+2.3.3.1	Citrate (Si)-synthase
+2.3.3.2	Decylcitrate synthase
+2.3.3.3	Citrate (Re)-synthase
+2.3.3.4	Decylhomocitrate synthase
+2.3.3.5	2-methylcitrate synthase
+2.3.3.6	2-ethylmalate synthase
+2.3.3.7	3-ethylmalate synthase
+2.3.3.8	ATP citrate synthase
+2.3.3.9	Malate synthase
+2.3.3.10	Hydroxymethylglutaryl-CoA synthase
+2.3.3.11	2-hydroxyglutarate synthase
+2.3.3.12	3-propylmalate synthase
+2.3.3.13	2-isopropylmalate synthase
+2.3.3.14	Homocitrate synthase
+2.3.3.15	Sulfoacetaldehyde acetyltransferase
+2.3.3.16	Citrate synthase (unknown stereospecificity)
+2.4.1.1	Glycogen phosphorylase
+2.4.1.2	Dextrin dextranase
+2.4.1.3	Transferred entry: 2.4.1.25
+2.4.1.4	Amylosucrase
+2.4.1.5	Dextransucrase
+2.4.1.6	Deleted entry
+2.4.1.7	Sucrose phosphorylase
+2.4.1.8	Maltose phosphorylase
+2.4.1.9	Inulosucrase
+2.4.1.10	Levansucrase
+2.4.1.11	Glycogen(starch) synthase
+2.4.1.12	Cellulose synthase (UDP-forming)
+2.4.1.13	Sucrose synthase
+2.4.1.14	Sucrose-phosphate synthase
+2.4.1.15	Alpha,alpha-trehalose-phosphate synthase (UDP-forming)
+2.4.1.16	Chitin synthase
+2.4.1.17	Glucuronosyltransferase
+2.4.1.18	1,4-alpha-glucan branching enzyme
+2.4.1.19	Cyclomaltodextrin glucanotransferase
+2.4.1.20	Cellobiose phosphorylase
+2.4.1.21	Starch synthase
+2.4.1.22	Lactose synthase
+2.4.1.23	Sphingosine beta-galactosyltransferase
+2.4.1.24	1,4-alpha-glucan 6-alpha-glucosyltransferase
+2.4.1.25	4-alpha-glucanotransferase
+2.4.1.26	DNA alpha-glucosyltransferase
+2.4.1.27	DNA beta-glucosyltransferase
+2.4.1.28	Glucosyl-DNA beta-glucosyltransferase
+2.4.1.29	Cellulose synthase (GDP-forming)
+2.4.1.30	1,3-beta-oligoglucan phosphorylase
+2.4.1.31	Laminaribiose phosphorylase
+2.4.1.32	Glucomannan 4-beta-mannosyltransferase
+2.4.1.33	Mannuronan synthase
+2.4.1.34	1,3-beta-glucan synthase
+2.4.1.35	Phenol beta-glucosyltransferase
+2.4.1.36	Alpha,alpha-trehalose-phosphate synthase (GDP-forming)
+2.4.1.37	Fucosylgalactoside 3-alpha-galactosyltransferase
+2.4.1.38	Beta-N-acetylglucosaminylglycopeptide beta-1,4-galactosyltransferase
+2.4.1.39	Steroid N-acetylglucosaminyltransferase
+2.4.1.40	Glycoprotein-fucosylgalactoside alpha-N-acetylgalactosaminyltransferase
+2.4.1.41	Polypeptide N-acetylgalactosaminyltransferase
+2.4.1.42	Transferred entry: 2.4.1.17
+2.4.1.43	Polygalacturonate 4-alpha-galacturonosyltransferase
+2.4.1.44	Lipopolysaccharide 3-alpha-galactosyltransferase
+2.4.1.45	2-hydroxyacylsphingosine 1-beta-galactosyltransferase
+2.4.1.46	Monogalactosyldiacylglycerol synthase
+2.4.1.47	N-acylsphingosine galactosyltransferase
+2.4.1.48	Heteroglycan alpha-mannosyltransferase
+2.4.1.49	Cellodextrin phosphorylase
+2.4.1.50	Procollagen galactosyltransferase
+2.4.1.51	Transferred entry: 2.4.1.101, 2.4.1.143, 2.4.1.144 and 2.4.1.145
+2.4.1.52	Poly(glycerol-phosphate) alpha-glucosyltransferase
+2.4.1.53	Poly(ribitol-phosphate) beta-glucosyltransferase
+2.4.1.54	Undecaprenyl-phosphate mannosyltransferase
+2.4.1.55	Transferred entry: 2.7.8.14
+2.4.1.56	Lipopolysaccharide N-acetylglucosaminyltransferase
+2.4.1.57	Phosphatidylinositol alpha-mannosyltransferase
+2.4.1.58	Lipopolysaccharide glucosyltransferase I
+2.4.1.59	Transferred entry: 2.4.1.17
+2.4.1.60	Abequosyltransferase
+2.4.1.61	Transferred entry: 2.4.1.17
+2.4.1.62	Ganglioside galactosyltransferase
+2.4.1.63	Linamarin synthase
+2.4.1.64	Alpha,alpha-trehalose phosphorylase
+2.4.1.65	3-galactosyl-N-acetylglucosaminide 4-alpha-L-fucosyltransferase
+2.4.1.66	Procollagen glucosyltransferase
+2.4.1.67	Galactinol--raffinose galactosyltransferase
+2.4.1.68	Glycoprotein 6-alpha-L-fucosyltransferase
+2.4.1.69	Galactoside 2-alpha-L-fucosyltransferase
+2.4.1.70	Poly(ribitol-phosphate) N-acetylglucosaminyltransferase
+2.4.1.71	Arylamine glucosyltransferase
+2.4.1.72	Transferred entry: 2.4.2.24
+2.4.1.73	Lipopolysaccharide glucosyltransferase II
+2.4.1.74	Glycosaminoglycan galactosyltransferase
+2.4.1.75	Deleted entry
+2.4.1.76	Transferred entry: 2.4.1.17
+2.4.1.77	Transferred entry: 2.4.1.17
+2.4.1.78	Phosphopolyprenol glucosyltransferase
+2.4.1.79	Globotriaosylceramide 3-beta-N-acetylgalactosaminyltransferase
+2.4.1.80	Ceramide glucosyltransferase
+2.4.1.81	Flavone 7-O-beta-glucosyltransferase
+2.4.1.82	Galactinol--sucrose galactosyltransferase
+2.4.1.83	Dolichyl-phosphate beta-D-mannosyltransferase
+2.4.1.84	Transferred entry: 2.4.1.17
+2.4.1.85	Cyanohydrin beta-glucosyltransferase
+2.4.1.86	Glucosaminylgalactosylglucosylceramide beta-galactosyltransferase
+2.4.1.87	N-acetyllactosaminide 3-alpha-galactosyltransferase
+2.4.1.88	Globoside alpha-N-acetylgalactosaminyltransferase
+2.4.1.89	Transferred entry: 2.4.1.69
+2.4.1.90	N-acetyllactosamine synthase
+2.4.1.91	Flavonol 3-O-glucosyltransferase
+2.4.1.92	N-acetylgalactosaminyltransferase
+2.4.1.93	Transferred entry: 4.2.2.18
+2.4.1.94	Protein N-acetylglucosaminyltransferase
+2.4.1.95	Bilirubin-glucuronoside glucuronosyltransferase
+2.4.1.96	sn-glycerol-3-phosphate 1-galactosyltransferase
+2.4.1.97	1,3-beta-D-glucan phosphorylase
+2.4.1.98	Transferred entry: 2.4.1.90
+2.4.1.99	Sucrose:sucrose fructosyltransferase
+2.4.1.100	2,1-fructan:2,1-fructan 1-fructosyltransferase
+2.4.1.101	Alpha-1,3-mannosyl-glycoprotein 2-beta-N-acetylglucosaminyltransferase
+2.4.1.102	acetylglucosaminyltransferase
+2.4.1.103	Alizarin 2-beta-glucosyltransferase
+2.4.1.104	o-dihydroxycoumarin 7-O-glucosyltransferase
+2.4.1.105	Vitexin beta-glucosyltransferase
+2.4.1.106	Isovitexin beta-glucosyltransferase
+2.4.1.107	Transferred entry: 2.4.1.17
+2.4.1.108	Transferred entry: 2.4.1.17
+2.4.1.109	Dolichyl-phosphate-mannose--protein mannosyltransferase
+2.4.1.110	tRNA-queuosine beta-mannosyltransferase
+2.4.1.111	Coniferyl-alcohol glucosyltransferase
+2.4.1.112	Transferred entry: 2.4.1.186
+2.4.1.113	Alpha-1,4-glucan-protein synthase (ADP-forming)
+2.4.1.114	2-coumarate O-beta-glucosyltransferase
+2.4.1.115	Anthocyanidin 3-O-glucosyltransferase
+2.4.1.116	Cyanidin 3-O-rutinoside 5-O-glucosyltransferase
+2.4.1.117	Dolichyl-phosphate beta-glucosyltransferase
+2.4.1.118	Cytokinin 7-beta-glucosyltransferase
+2.4.1.119	Transferred entry: 2.4.99.18
+2.4.1.120	Sinapate 1-glucosyltransferase
+2.4.1.121	Indole-3-acetate beta-glucosyltransferase
+2.4.1.122	Glycoprotein-N-acetylgalactosamine 3-beta-galactosyltransferase
+2.4.1.123	Inositol 3-alpha-galactosyltransferase
+2.4.1.124	Transferred entry: 2.4.1.87
+2.4.1.125	Sucrose--1,6-alpha-glucan 3(6)-alpha-glucosyltransferase
+2.4.1.126	Hydroxycinnamate 4-beta-glucosyltransferase
+2.4.1.127	Monoterpenol beta-glucosyltransferase
+2.4.1.128	Scopoletin glucosyltransferase
+2.4.1.129	Peptidoglycan glycosyltransferase
+2.4.1.130	Transferred entry: 2.4.1.258, 2.4.1.259, 2.4.1.260 and 2.4.1.261
+2.4.1.131	GDP-Man:Man(3)GlcNAc(2)-PP-dolichol alpha-1,2-mannosyltransferase
+2.4.1.132	GDP-Man:Man(1)GlcNAc(2)-PP-dolichol alpha-1,3-mannosyltransferase
+2.4.1.133	Xylosylprotein 4-beta-galactosyltransferase
+2.4.1.134	Galactosylxylosylprotein 3-beta-galactosyltransferase
+2.4.1.135	Galactosylgalactosylxylosylprotein 3-beta-glucuronosyltransferase
+2.4.1.136	Gallate 1-beta-glucosyltransferase
+2.4.1.137	sn-glycerol-3-phosphate 2-alpha-galactosyltransferase
+2.4.1.138	Mannotetraose 2-alpha-N-acetylglucosaminyltransferase
+2.4.1.139	Maltose synthase
+2.4.1.140	Alternansucrase
+2.4.1.141	N-acetylglucosaminyldiphosphodolichol N-acetylglucosaminyltransferase
+2.4.1.142	Chitobiosyldiphosphodolichol beta-mannosyltransferase
+2.4.1.143	Alpha-1,6-mannosyl-glycoprotein 2-beta-N-acetylglucosaminyltransferase
+2.4.1.144	Beta-1,4-mannosyl-glycoprotein 4-beta-N-acetylglucosaminyltransferase
+2.4.1.145	Alpha-1,3-mannosyl-glycoprotein 4-beta-N-acetylglucosaminyltransferase
+2.4.1.146	acetylglucosaminyltransferase
+2.4.1.147	acetylglucosaminyltransferase
+2.4.1.148	acetylglucosaminyltransferase
+2.4.1.149	N-acetyllactosaminide beta-1,3-N-acetylglucosaminyltransferase
+2.4.1.150	N-acetyllactosaminide beta-1,6-N-acetylglucosaminyl-transferase
+2.4.1.151	Transferred entry: 2.4.1.87
+2.4.1.152	4-galactosyl-N-acetylglucosaminide 3-alpha-L-fucosyltransferase
+2.4.1.153	N-acetylglucosaminyltransferase
+2.4.1.154	Deleted entry
+2.4.1.155	Alpha-1,6-mannosyl-glycoprotein 6-beta-N-acetylglucosaminyltransferase
+2.4.1.156	Indolylacetyl-myo-inositol galactosyltransferase
+2.4.1.157	1,2-diacylglycerol 3-glucosyltransferase
+2.4.1.158	13-hydroxydocosanoate 13-beta-glucosyltransferase
+2.4.1.159	Flavonol-3-O-glucoside L-rhamnosyltransferase
+2.4.1.160	Pyridoxine 5'-O-beta-D-glucosyltransferase
+2.4.1.161	Oligosaccharide 4-alpha-D-glucosyltransferase
+2.4.1.162	Aldose beta-D-fructosyltransferase
+2.4.1.163	acetylglucosaminyltransferase
+2.4.1.164	acetylglucosaminyltransferase
+2.4.1.165	acetylgalactosaminyltransferase
+2.4.1.166	Raffinose--raffinose alpha-galactosyltransferase
+2.4.1.167	Sucrose 6(F)-alpha-galactosyltransferase
+2.4.1.168	Xyloglucan 4-glucosyltransferase
+2.4.1.169	Transferred entry: 2.4.2.39
+2.4.1.170	Isoflavone 7-O-glucosyltransferase
+2.4.1.171	Methyl-ONN-azoxymethanol beta-D-glucosyltransferase
+2.4.1.172	Salicyl-alcohol beta-D-glucosyltransferase
+2.4.1.173	Sterol 3-beta-glucosyltransferase
+2.4.1.174	acetylgalactosaminyltransferase
+2.4.1.175	acetylgalactosaminyltransferase
+2.4.1.176	Gibberellin beta-D-glucosyltransferase
+2.4.1.177	Cinnamate beta-D-glucosyltransferase
+2.4.1.178	Hydroxymandelonitrile glucosyltransferase
+2.4.1.179	Lactosylceramide beta-1,3-galactosyltransferase
+2.4.1.180	Lipopolysaccharide N-acetylmannosaminouronosyltransferase
+2.4.1.181	Hydroxyanthraquinone glucosyltransferase
+2.4.1.182	Lipid-A-disaccharide synthase
+2.4.1.183	Alpha-1,3-glucan synthase
+2.4.1.184	Galactolipid galactosyltransferase
+2.4.1.185	Flavanone 7-O-beta-glucosyltransferase
+2.4.1.186	Glycogenin glucosyltransferase
+2.4.1.187	mannosaminyltransferase
+2.4.1.188	N-acetylglucosaminyldiphosphoundecaprenol glucosyltransferase
+2.4.1.189	Luteolin 7-O-glucuronosyltransferase
+2.4.1.190	Luteolin-7-O-glucuronide 2''-O-glucuronosyltransferase
+2.4.1.191	Luteolin-7-O-diglucuronide 4'-O-glucuronosyltransferase
+2.4.1.192	Nuatigenin 3-beta-glucosyltransferase
+2.4.1.193	Sarsapogenin 3-beta-glucosyltransferase
+2.4.1.194	4-hydroxybenzoate 4-O-beta-D-glucosyltransferase
+2.4.1.195	N-hydroxythioamide S-beta-glucosyltransferase
+2.4.1.196	Nicotinate glucosyltransferase
+2.4.1.197	High-mannose-oligosaccharide beta-1,4-N-acetylglucosaminyltransferase
+2.4.1.198	Phosphatidylinositol N-acetylglucosaminyltransferase
+2.4.1.199	6-mannosyltransferase
+2.4.1.200	Transferred entry: 4.2.2.17
+2.4.1.201	Alpha-1,6-mannosyl-glycoprotein 4-beta-N-acetylglucosaminyltransferase
+2.4.1.202	glucosyltransferase
+2.4.1.203	Trans-zeatin O-beta-D-glucosyltransferase
+2.4.1.204	Transferred entry: 2.4.2.40
+2.4.1.205	Galactogen 6-beta-galactosyltransferase
+2.4.1.206	Lactosylceramide 1,3-N-acetyl-beta-D-glucosaminyltransferase
+2.4.1.207	Xyloglucan:xyloglucosyl transferase
+2.4.1.208	Diglucosyl diacylglycerol synthase (1,2-linking)
+2.4.1.209	Cis-p-coumarate glucosyltransferase
+2.4.1.210	Limonoid glucosyltransferase
+2.4.1.211	1,3-beta-galactosyl-N-acetylhexosamine phosphorylase
+2.4.1.212	Hyaluronan synthase
+2.4.1.213	Glucosylglycerol-phosphate synthase
+2.4.1.214	Glycoprotein 3-alpha-L-fucosyltransferase
+2.4.1.215	Cis-zeatin O-beta-D-glucosyltransferase
+2.4.1.216	Trehalose 6-phosphate phosphorylase
+2.4.1.217	Mannosyl-3-phosphoglycerate synthase
+2.4.1.218	Hydroquinone glucosyltransferase
+2.4.1.219	Vomilenine glucosyltransferase
+2.4.1.220	Indoxyl-UDPG glucosyltransferase
+2.4.1.221	Peptide-O-fucosyltransferase
+2.4.1.222	O-fucosylpeptide 3-beta-N-acetylglucosaminyltransferase
+2.4.1.223	acetylglucosaminyltransferase
+2.4.1.224	acetylglucosaminyltransferase
+2.4.1.225	N-acetylglucosaminyl-proteoglycan 4-beta-glucuronosyltransferase
+2.4.1.226	N-acetylgalactosaminyl-proteoglycan 3-beta-glucuronosyltransferase
+2.4.1.227	acetylglucosaminyltransferase
+2.4.1.228	Lactosylceramide 4-alpha-galactosyltransferase
+2.4.1.229	[Skp1-protein]-hydroxyproline N-acetylglucosaminyltransferase
+2.4.1.230	Kojibiose phosphorylase
+2.4.1.231	Alpha,alpha-trehalose phosphorylase (configuration-retaining)
+2.4.1.232	Initiation-specific alpha-1,6-mannosyltransferase
+2.4.1.233	Transferred entry: 2.4.1.115
+2.4.1.234	Kaempferol 3-O-galactosyltransferase
+2.4.1.235	Deleted entry
+2.4.1.236	Flavanone 7-O-glucoside 2''-O-beta-L-rhamnosyltransferase
+2.4.1.237	Flavonol 7-O-beta-glucosyltransferase
+2.4.1.238	Delphinidin 3,5-di-O-glucoside 3'-O-glucosyltransferase
+2.4.1.239	Flavonol-3-O-glucoside glucosyltransferase
+2.4.1.240	Flavonol-3-O-glycoside glucosyltransferase
+2.4.1.241	Digalactosyldiacylglycerol synthase
+2.4.1.242	NDP-glucose--starch glucosyltransferase
+2.4.1.243	6(G)-fructosyltransferase
+2.4.1.244	acetylgalactosaminyltransferase
+2.4.1.245	Alpha,alpha-trehalose synthase
+2.4.1.246	Mannosylfructose-phosphate synthase
+2.4.1.247	Beta-D-galactosyl-(1->4)-L-rhamnose phosphorylase
+2.4.1.248	Cycloisomaltooligosaccharide glucanotransferase
+2.4.1.249	Delphinidin 3',5'-O-glucosyltransferase
+2.4.1.250	D-inositol-3-phosphate glycosyltransferase
+2.4.1.251	diphospho-ditrans,octacis-undecaprenol 4-beta-mannosyltransferase
+2.4.1.252	GDP-mannose:cellobiosyl-diphosphopolyprenol alpha-mannosyltransferase
+2.4.1.253	Baicalein 7-O-glucuronosyltransferase
+2.4.1.254	Cyanidin-3-O-glucoside 2''-O-glucuronosyltransferase
+2.4.1.255	Protein O-GlcNAc transferase
+2.4.1.256	glucosyltransferase
+2.4.1.257	GDP-Man:Man(2)GlcNAc(2)-PP-dolichol alpha-1,6-mannosyltransferase
+2.4.1.258	Dolichyl-P-Man:Man(5)GlcNAc(2)-PP-dolichol alpha-1,3-mannosyltransferase
+2.4.1.259	Dolichyl-P-Man:Man(6)GlcNAc(2)-PP-dolichol alpha-1,2-mannosyltransferase
+2.4.1.260	Dolichyl-P-Man:Man(7)GlcNAc(2)-PP-dolichol alpha-1,6-mannosyltransferase
+2.4.1.261	Dolichyl-P-Man:Man(8)GlcNAc(2)-PP-dolichol alpha-1,2-mannosyltransferase
+2.4.1.262	Soyasapogenol glucuronosyltransferase
+2.4.1.263	Abscisate beta-glucosyltransferase
+2.4.1.264	2-beta-glucuronyltransferase
+2.4.1.265	glucosyltransferase
+2.4.1.266	Glucosyl-3-phosphoglycerate synthase
+2.4.1.267	Dolichyl-P-Glc:Man(9)GlcNAc(2)-PP-dolichol alpha-1,3-glucosyltransferase
+2.4.1.268	Glucosylglycerate synthase
+2.4.1.269	Mannosylglycerate synthase
+2.4.1.270	Mannosylglucosyl-3-phosphoglycerate synthase
+2.4.1.271	Crocetin glucosyltransferase
+2.4.1.272	Soyasapogenol B glucuronide galactosyltransferase
+2.4.1.273	Soyasaponin III rhamnosyltransferase
+2.4.1.274	Glucosylceramide beta-1,4-galactosyltransferase
+2.4.1.275	Neolactotriaosylceramide beta-1,4-galactosyltransferase
+2.4.1.276	Zeaxanthin glucosyltransferase
+2.4.1.277	10-deoxymethynolide desosaminyltransferase
+2.4.1.278	3-alpha-mycarosylerythronolide B desosaminyl transferase
+2.4.1.279	Nigerose phosphorylase
+2.4.1.280	N,N'-diacetylchitobiose phosphorylase
+2.4.1.281	4-O-beta-D-mannosyl-D-glucose phosphorylase
+2.4.1.282	3-O-alpha-D-glucosyl-L-rhamnose phosphorylase
+2.4.1.283	2-deoxystreptamine N-acetyl-D-glucosaminyltransferase
+2.4.1.284	2-deoxystreptamine glucosyltransferase
+2.4.1.285	UDP-GlcNAc:ribostamycin N-acetylglucosaminyltransferase
+2.4.1.286	Chalcone 4'-O-glucosyltransferase
+2.4.1.287	galactofuranosyltransferase
+2.4.1.288	decaprenol beta-1,5/1,6-galactofuranosyltransferase
+2.4.1.289	N-acetylglucosaminyl-diphospho-decaprenol L-rhamnosyltransferase
+2.4.1.290	acetylgalactosaminyltransferase
+2.4.1.291	4-alpha-N-acetylgalactosaminyltransferase
+2.4.1.292	1,4-N-acetyl-D-galactosaminyltransferase
+2.4.1.293	GalNAc(5)-diNAcBac-PP-undecaprenol beta-1,3-glucosyltransferase
+2.4.1.294	Cyanidin 3-O-galactosyltransferase
+2.4.1.295	Anthocyanin 3-O-sambubioside 5-O-glucosyltransferase
+2.4.1.296	Anthocyanidin 3-O-coumaroylrutinoside 5-O-glucosyltransferase
+2.4.1.297	Anthocyanidin 3-O-glucoside 2''-O-glucosyltransferase
+2.4.1.298	Anthocyanidin 3-O-glucoside 5-O-glucosyltransferase
+2.4.1.299	Cyanidin 3-O-glucoside 5-O-glucosyltransferase (acyl-glucose)
+2.4.1.300	Cyanidin 3-O-glucoside 7-O-glucosyltransferase (acyl-glucose)
+2.4.1.301	2'-deamino-2'-hydroxyneamine 1-alpha-D-kanosaminyltransferase
+2.4.1.302	L-demethylnoviosyl transferase
+2.4.1.303	galactosyltransferase
+2.4.1.304	galactosyltransferase
+2.4.1.305	glucosyltransferase
+2.4.1.306	acetylgalactosaminyltransferase
+2.4.1.307	galactosyltransferase
+2.4.1.308	diphosphoundecaprenol alpha-1,2-fucosyltransferase
+2.4.1.309	diphosphoundecaprenol alpha-1,3-galactosyltransferase
+2.4.1.310	Vancomycin aglycone glucosyltransferase
+2.4.1.311	dTDP-epi-vancosaminyltransferase
+2.4.1.312	Protein O-mannose beta-1,4-N-acetylglucosaminyltransferase
+2.4.1.313	Protein O-mannose beta-1,3-N-acetylgalactosaminyltransferase
+2.4.1.314	Ginsenoside Rd glucosyltransferase
+2.4.1.315	Diglucosyl diacylglycerol synthase (1,6-linking)
+2.4.1.316	Tylactone mycaminosyltransferase
+2.4.1.317	O-mycaminosyltylonolide 6-deoxyallosyltransferase
+2.4.1.318	Demethyllactenocin mycarosyltransferase
+2.4.1.319	Beta-1,4-mannooligosaccharide phosphorylase
+2.4.1.320	1,4-beta-mannosyl-N-acetylglucosamine phosphorylase
+2.4.1.321	Cellobionic acid phosphorylase
+2.4.1.322	Devancosaminyl-vancomycin vancosaminetransferase
+2.4.1.323	7-deoxyloganetic acid glucosyltransferase
+2.4.1.324	7-deoxyloganetin glucosyltransferase
+2.4.1.325	TDP-N-acetylfucosamine:lipid II N-acetylfucosaminyltransferase
+2.4.1.326	Aklavinone 7-L-rhodosaminyltransferase
+2.4.1.327	Aclacinomycin-T 2-deoxy-L-fucose transferase
+2.4.1.328	Erythronolide mycarosyltransferase
+2.4.1.329	Sucrose 6(F)-phosphate phosphorylase
+2.4.1.330	Beta-D-glucosyl crocetin beta-1,6-glucosyltransferase
+2.4.1.331	8-demethyltetracenomycin C L-rhamnosyltransferase
+2.4.1.332	1,2-alpha-glucosylglycerol phosphorylase
+2.4.1.333	1,2-beta-oligoglucan phosphorylase
+2.4.1.334	1,3-alpha-oligoglucan phosphorylase
+2.4.1.335	diacetamido-2,3-dideoxy-beta-D-glucuronosyltransferase
+2.4.1.336	Monoglucosyldiacylglycerol synthase
+2.4.1.337	1,2-diacylglycerol 3-alpha-glucosyltransferase
+2.4.2.1	Purine-nucleoside phosphorylase
+2.4.2.2	Pyrimidine-nucleoside phosphorylase
+2.4.2.3	Uridine phosphorylase
+2.4.2.4	Thymidine phosphorylase
+2.4.2.5	Nucleoside ribosyltransferase
+2.4.2.6	Nucleoside deoxyribosyltransferase
+2.4.2.7	Adenine phosphoribosyltransferase
+2.4.2.8	Hypoxanthine phosphoribosyltransferase
+2.4.2.9	Uracil phosphoribosyltransferase
+2.4.2.10	Orotate phosphoribosyltransferase
+2.4.2.11	Transferred entry: 6.3.4.21
+2.4.2.12	Nicotinamide phosphoribosyltransferase
+2.4.2.13	Transferred entry: 2.5.1.6
+2.4.2.14	Amidophosphoribosyltransferase
+2.4.2.15	Guanosine phosphorylase
+2.4.2.16	Urate-ribonucleotide phosphorylase
+2.4.2.17	ATP phosphoribosyltransferase
+2.4.2.18	Anthranilate phosphoribosyltransferase
+2.4.2.19	Nicotinate-nucleotide diphosphorylase (carboxylating)
+2.4.2.20	Dioxotetrahydropyrimidine phosphoribosyltransferase
+2.4.2.21	Nicotinate-nucleotide--dimethylbenzimidazole phosphoribosyltransferase
+2.4.2.22	Xanthine phosphoribosyltransferase
+2.4.2.23	Transferred entry: 2.4.2.2, 2.4.2.3 and 2.4.2.4
+2.4.2.24	1,4-beta-D-xylan synthase
+2.4.2.25	Flavone apiosyltransferase
+2.4.2.26	Protein xylosyltransferase
+2.4.2.27	dihydrostreptosyltransferase
+2.4.2.28	S-methyl-5'-thioadenosine phosphorylase
+2.4.2.29	tRNA-guanine(34) transglycosylase
+2.4.2.30	NAD(+) ADP-ribosyltransferase
+2.4.2.31	NAD(+)--protein-arginine ADP-ribosyltransferase
+2.4.2.32	Dolichyl-phosphate D-xylosyltransferase
+2.4.2.33	Dolichyl-xylosyl-phosphate--protein xylosyltransferase
+2.4.2.34	Indolylacetylinositol arabinosyltransferase
+2.4.2.35	Flavonol-3-O-glycoside xylosyltransferase
+2.4.2.36	NAD(+)--diphthamide ADP-ribosyltransferase
+2.4.2.37	NAD(+)--dinitrogen-reductase ADP-D-ribosyltransferase
+2.4.2.38	Glycoprotein 2-beta-D-xylosyltransferase
+2.4.2.39	Xyloglucan 6-xylosyltransferase
+2.4.2.40	Zeatin O-beta-D-xylosyltransferase
+2.4.2.41	Xylogalacturonan beta-1,3-xylosyltransferase
+2.4.2.42	UDP-D-xylose:beta-D-glucoside alpha-1,3-D-xylosyltransferase
+2.4.2.43	Lipid IV(A) 4-amino-4-deoxy-L-arabinosyltransferase
+2.4.2.44	S-methyl-5'-thioinosine phosphorylase
+2.4.2.45	Decaprenyl-phosphate phosphoribosyltransferase
+2.4.2.46	Galactan 5-O-arabinofuranosyltransferase
+2.4.2.47	Arabinofuranan 3-O-arabinosyltransferase
+2.4.2.48	tRNA-guanine(15) transglycosylase
+2.4.2.49	Neamine phosphoribosyltransferase
+2.4.2.50	Cyanidin 3-O-galactoside 2''-O-xylosyltransferase
+2.4.2.51	Anthocyanidin 3-O-glucoside 2'''-O-xylosyltransferase
+2.4.2.52	Triphosphoribosyl-dephospho-CoA synthase
+2.4.2.53	Undecaprenyl-phosphate 4-deoxy-4-formamido-L-arabinose transferase
+2.4.2.54	Beta-ribofuranosylphenol 5'-phosphate synthase
+2.4.2.55	Nicotinate D-ribonucleotide:phenol phospho-D-ribosyltransferase
+2.4.2.56	Kaempferol 3-O-xylosyltransferase
+2.4.2.57	AMP phosphorylase
+2.4.99.1	Beta-galactoside alpha-2,6-sialyltransferase
+2.4.99.2	Monosialoganglioside sialyltransferase
+2.4.99.3	Alpha-N-acetylgalactosaminide alpha-2,6-sialyltransferase
+2.4.99.4	Beta-galactoside alpha-2,3-sialyltransferase
+2.4.99.5	Galactosyldiacylglycerol alpha-2,3-sialyltransferase
+2.4.99.6	N-acetyllactosaminide alpha-2,3-sialyltransferase
+2.4.99.7	6-alpha-sialyltransferase
+2.4.99.8	Alpha-N-acetylneuraminate alpha-2,8-sialyltransferase
+2.4.99.9	Lactosylceramide alpha-2,3-sialyltransferase
+2.4.99.10	Neolactotetraosylceramide alpha-2,3-sialyltransferase
+2.4.99.11	Lactosylceramide alpha-2,6-N-sialyltransferase
+2.4.99.12	Lipid IV(A) 3-deoxy-D-manno-octulosonic acid transferase
+2.4.99.13	(Kdo)-lipid IV(A) 3-deoxy-D-manno-octulosonic acid transferase
+2.4.99.14	(Kdo)(2)-lipid IV(A) (2-8) 3-deoxy-D-manno-octulosonic acid transferase
+2.4.99.15	(Kdo)(3)-lipid IV(A) (2-4) 3-deoxy-D-manno-octulosonic acid transferase
+2.4.99.16	Starch synthase (maltosyl-transferring)
+2.4.99.17	S-adenosylmethionine:tRNA ribosyltransferase-isomerase
+2.4.99.18	Dolichyl-diphosphooligosaccharide--protein glycotransferase
+2.4.99.19	Undecaprenyl-diphosphooligosaccharide--protein glycotransferase
+2.4.99.20	2'-phospho-ADP-ribosyl cyclase/2'-phospho-cyclic-ADP-ribose transferase
+2.4.99.21	Dolichyl-phosphooligosaccharide-protein glycotransferase
+2.5.1.1	Dimethylallyltranstransferase
+2.5.1.2	Thiamine pyridinylase
+2.5.1.3	Thiamine phosphate synthase
+2.5.1.4	Adenosylmethionine cyclotransferase
+2.5.1.5	Galactose-6-sulfurylase
+2.5.1.6	Methionine adenosyltransferase
+2.5.1.7	UDP-N-acetylglucosamine 1-carboxyvinyltransferase
+2.5.1.8	Transferred entry: 2.5.1.75
+2.5.1.9	Riboflavin synthase
+2.5.1.10	(2E,6E)-farnesyl diphosphate synthase
+2.5.1.11	Transferred entry: 2.5.1.84 and 2.5.1.85
+2.5.1.12	Transferred entry: 2.5.1.18
+2.5.1.13	Transferred entry: 2.5.1.18
+2.5.1.14	Transferred entry: 2.5.1.18
+2.5.1.15	Dihydropteroate synthase
+2.5.1.16	Spermidine synthase
+2.5.1.17	Cob(I)yrinic acid a,c-diamide adenosyltransferase
+2.5.1.18	Glutathione transferase
+2.5.1.19	3-phosphoshikimate 1-carboxyvinyltransferase
+2.5.1.20	Rubber cis-polyprenylcistransferase
+2.5.1.21	Squalene synthase
+2.5.1.22	Spermine synthase
+2.5.1.23	Sym-norspermidine synthase
+2.5.1.24	Discadenine synthase
+2.5.1.25	tRNA-uridine aminocarboxypropyltransferase
+2.5.1.26	Alkylglycerone-phosphate synthase
+2.5.1.27	Adenylate dimethylallyltransferase (AMP-dependent)
+2.5.1.28	Dimethylallylcistransferase
+2.5.1.29	Geranylgeranyl diphosphate synthase
+2.5.1.30	Heptaprenyl diphosphate synthase
+2.5.1.31	diphosphate specific)
+2.5.1.32	15-cis-phytoene synthase
+2.5.1.33	Transferred entry: 2.5.1.82 and 2.5.1.83
+2.5.1.34	4-dimethylallyltryptophan synthase
+2.5.1.35	Aspulvinone dimethylallyltransferase
+2.5.1.36	Trihydroxypterocarpan dimethylallyltransferase
+2.5.1.37	Transferred entry: 4.4.1.20
+2.5.1.38	Isonocardicin synthase
+2.5.1.39	4-hydroxybenzoate polyprenyltransferase
+2.5.1.40	Transferred entry: 4.2.3.9
+2.5.1.41	Phosphoglycerol geranylgeranyltransferase
+2.5.1.42	Geranylgeranylglycerol-phosphate geranylgeranyltransferase
+2.5.1.43	Nicotianamine synthase
+2.5.1.44	Homospermidine synthase
+2.5.1.45	Homospermidine synthase (spermidine-specific)
+2.5.1.46	Deoxyhypusine synthase
+2.5.1.47	Cysteine synthase
+2.5.1.48	Cystathionine gamma-synthase
+2.5.1.49	O-acetylhomoserine aminocarboxypropyltransferase
+2.5.1.50	Zeatin 9-aminocarboxyethyltransferase
+2.5.1.51	Beta-pyrazolylalanine synthase
+2.5.1.52	L-mimosine synthase
+2.5.1.53	Uracilylalanine synthase
+2.5.1.54	3-deoxy-7-phosphoheptulonate synthase
+2.5.1.55	3-deoxy-8-phosphooctulonate synthase
+2.5.1.56	N-acetylneuraminate synthase
+2.5.1.57	N-acylneuraminate-9-phosphate synthase
+2.5.1.58	Protein farnesyltransferase
+2.5.1.59	Protein geranylgeranyltransferase type I
+2.5.1.60	Protein geranylgeranyltransferase type II
+2.5.1.61	Hydroxymethylbilane synthase
+2.5.1.62	Chlorophyll synthase
+2.5.1.63	Adenosyl-fluoride synthase
+2.5.1.64	Transferred entry: 2.2.1.9 and 4.2.99.20
+2.5.1.65	O-phosphoserine sulfhydrylase
+2.5.1.66	N(2)-(2-carboxyethyl)arginine synthase
+2.5.1.67	Chrysanthemyl diphosphate synthase
+2.5.1.68	(2Z,6E)-farnesyl diphosphate synthase
+2.5.1.69	Lavandulyl diphosphate synthase
+2.5.1.70	Naringenin 8-dimethylallyltransferase
+2.5.1.71	Leachianone-G 2''-dimethylallyltransferase
+2.5.1.72	Quinolinate synthase
+2.5.1.73	O-phospho-L-seryl-tRNA:Cys-tRNA synthase
+2.5.1.74	1,4-dihydroxy-2-naphthoate polyprenyltransferase
+2.5.1.75	tRNA dimethylallyltransferase
+2.5.1.76	Cysteate synthase
+2.5.1.77	7,8-didemethyl-8-hydroxy-5-deazariboflavin synthase
+2.5.1.78	6,7-dimethyl-8-ribityllumazine synthase
+2.5.1.79	Thermospermine synthase
+2.5.1.80	7-dimethylallyltryptophan synthase
+2.5.1.81	Geranylfarnesyl diphosphate synthase
+2.5.1.82	Hexaprenyl diphosphate synthase (geranylgeranyl-diphosphate specific)
+2.5.1.83	Hexaprenyl-diphosphate synthase ((2E,6E)-farnesyl-diphosphate specific)
+2.5.1.84	All-trans-nonaprenyl-diphosphate synthase (geranyl-diphosphate specific)
+2.5.1.85	specific)
+2.5.1.86	Trans,polycis-decaprenyl diphosphate synthase
+2.5.1.87	diphosphate specific)
+2.5.1.88	diphosphate specific)
+2.5.1.89	diphosphate specific)
+2.5.1.90	All-trans-octaprenyl-diphosphate synthase
+2.5.1.91	All-trans-decaprenyl-diphosphate synthase
+2.5.1.92	(2Z,6Z)-farnesyl diphosphate synthase
+2.5.1.93	4-hydroxybenzoate geranyltransferase
+2.5.1.94	Adenosyl-chloride synthase
+2.5.1.95	Xanthan pyruvate transferase
+2.5.1.96	4,4'-diapophytoene synthase
+2.5.1.97	Pseudaminic acid synthase
+2.5.1.98	transferase
+2.5.1.99	All-trans-phytoene synthase
+2.5.1.100	Fumigaclavine A dimethylallyltransferase
+2.5.1.101	N,N'-diacetyllegionaminate synthase
+2.5.1.102	Geranylpyrophosphate--olivetolic acid geranyltransferase
+2.5.1.103	Presqualene diphosphate synthase
+2.5.1.104	N(1)-aminopropylagmatine synthase
+2.5.1.105	5'-phosphate synthase
+2.5.1.106	Tryprostatin B synthase
+2.5.1.107	Verruculogen prenyltransferase
+2.5.1.108	2-(3-amino-3-carboxypropyl)histidine synthase
+2.5.1.109	Brevianamide F prenyltransferase (deoxybrevianamide E-forming)
+2.5.1.110	12-alpha,13-alpha-dihydroxyfumitremorgin C prenyltransferase
+2.5.1.111	4-hydroxyphenylpyruvate 3-dimethylallyltransferase
+2.5.1.112	Adenylate dimethylallyltransferase (ADP/ATP-dependent)
+2.5.1.113	synthase
+2.5.1.114	tRNA(Phe) (4-demethylwyosine(37)-C(7)) aminocarboxypropyltransferase
+2.5.1.115	Homogentisate phytyltransferase
+2.5.1.116	Homogentisate geranylgeranyltransferase
+2.5.1.117	Homogentisate solanesyltransferase
+2.5.1.118	Beta-(isoxazolin-5-on-2-yl)-L-alanine synthase
+2.5.1.119	Beta-(isoxazolin-5-on-4-yl)-L-alanine synthase
+2.5.1.120	Aminodeoxyfutalosine synthase
+2.5.1.121	5,10-dihydrophenazine-1-carboxylate 9-dimethylallyltransferase
+2.5.1.122	4-O-dimethylallyl-L-tyrosine synthase
+2.5.1.123	Flaviolin linalyltransferase
+2.5.1.124	6-linalyl-2-O,3-dimethylflaviolin synthase
+2.5.1.125	7-geranyloxy-5-hydroxy-2-methoxy-3-methylnaphthalene-1,4-dione synthase
+2.5.1.126	Norspermine synthase
+2.5.1.127	Caldopentamine synthase
+2.5.1.128	N(4)-bis(aminopropyl)spermidine synthase
+2.5.1.129	Flavin prenyltransferase
+2.5.1.130	2-carboxy-1,4-naphthoquinone phytyltransferase
+2.5.1.131	yl)methanamine synthase
+2.6.1.1	Aspartate transaminase
+2.6.1.2	Alanine transaminase
+2.6.1.3	Cysteine transaminase
+2.6.1.4	Glycine transaminase
+2.6.1.5	Tyrosine transaminase
+2.6.1.6	Leucine transaminase
+2.6.1.7	Kynurenine--oxoglutarate transaminase
+2.6.1.8	2,5-diaminovalerate transaminase
+2.6.1.9	Histidinol-phosphate transaminase
+2.6.1.10	Transferred entry: 2.6.1.21
+2.6.1.11	Acetylornithine transaminase
+2.6.1.12	Alanine--oxo-acid transaminase
+2.6.1.13	Ornithine aminotransferase
+2.6.1.14	Asparagine--oxo-acid transaminase
+2.6.1.15	Glutamine--pyruvate transaminase
+2.6.1.16	Glutamine--fructose-6-phosphate transaminase (isomerizing)
+2.6.1.17	Succinyldiaminopimelate transaminase
+2.6.1.18	Beta-alanine--pyruvate transaminase
+2.6.1.19	4-aminobutyrate--2-oxoglutarate transaminase
+2.6.1.20	Deleted entry
+2.6.1.21	D-amino-acid transaminase
+2.6.1.22	(S)-3-amino-2-methylpropionate transaminase
+2.6.1.23	4-hydroxyglutamate transaminase
+2.6.1.24	Diiodotyrosine transaminase
+2.6.1.25	Transferred entry: 2.6.1.24
+2.6.1.26	Thyroid-hormone transaminase
+2.6.1.27	Tryptophan transaminase
+2.6.1.28	Tryptophan--phenylpyruvate transaminase
+2.6.1.29	Diamine transaminase
+2.6.1.30	Pyridoxamine--pyruvate transaminase
+2.6.1.31	Pyridoxamine--oxaloacetate transaminase
+2.6.1.32	Valine--3-methyl-2-oxovalerate transaminase
+2.6.1.33	dTDP-4-amino-4,6-dideoxy-D-glucose transaminase
+2.6.1.34	UDP-N-acetylbacillosamine transaminase
+2.6.1.35	Glycine--oxaloacetate transaminase
+2.6.1.36	L-lysine 6-transaminase
+2.6.1.37	2-aminoethylphosphonate--pyruvate transaminase
+2.6.1.38	Histidine transaminase
+2.6.1.39	2-aminoadipate transaminase
+2.6.1.40	(R)-3-amino-2-methylpropionate--pyruvate transaminase
+2.6.1.41	D-methionine--pyruvate transaminase
+2.6.1.42	Branched-chain-amino-acid transaminase
+2.6.1.43	Aminolevulinate transaminase
+2.6.1.44	Alanine--glyoxylate transaminase
+2.6.1.45	Serine--glyoxylate transaminase
+2.6.1.46	Diaminobutyrate--pyruvate transaminase
+2.6.1.47	Alanine--oxomalonate transaminase
+2.6.1.48	5-aminovalerate transaminase
+2.6.1.49	Dihydroxyphenylalanine transaminase
+2.6.1.50	Glutamine--scyllo-inositol transaminase
+2.6.1.51	Serine--pyruvate transaminase
+2.6.1.52	Phosphoserine transaminase
+2.6.1.53	Transferred entry: 1.4.1.13
+2.6.1.54	Pyridoxamine-phosphate transaminase
+2.6.1.55	Taurine--2-oxoglutarate transaminase
+2.6.1.56	1D-1-guanidino-3-amino-1,3-dideoxy-scyllo-inositol transaminase
+2.6.1.57	Aromatic-amino-acid transaminase
+2.6.1.58	Phenylalanine(histidine) transaminase
+2.6.1.59	dTDP-4-amino-4,6-dideoxygalactose transaminase
+2.6.1.60	Aromatic-amino-acid--glyoxylate transaminase
+2.6.1.61	Transferred entry: 2.6.1.40
+2.6.1.62	Adenosylmethionine--8-amino-7-oxononanoate transaminase
+2.6.1.63	Kynurenine--glyoxylate transaminase
+2.6.1.64	Glutamine--phenylpyruvate transaminase
+2.6.1.65	N(6)-acetyl-beta-lysine transaminase
+2.6.1.66	Valine--pyruvate transaminase
+2.6.1.67	2-aminohexanoate transaminase
+2.6.1.68	Ornithine(lysine) transaminase
+2.6.1.69	Deleted entry
+2.6.1.70	Aspartate--phenylpyruvate transaminase
+2.6.1.71	Lysine--pyruvate 6-transaminase
+2.6.1.72	D-4-hydroxyphenylglycine transaminase
+2.6.1.73	Methionine--glyoxylate transaminase
+2.6.1.74	Cephalosporin-C transaminase
+2.6.1.75	Cysteine-conjugate transaminase
+2.6.1.76	Diaminobutyrate--2-oxoglutarate transaminase
+2.6.1.77	Taurine--pyruvate aminotransferase
+2.6.1.78	Aspartate--prephenate aminotransferase
+2.6.1.79	Glutamate--prephenate aminotransferase
+2.6.1.80	Nicotianamine aminotransferase
+2.6.1.81	Succinylornithine transaminase
+2.6.1.82	Putrescine aminotransferase
+2.6.1.83	LL-diaminopimelate aminotransferase
+2.6.1.84	Arginine--pyruvate transaminase
+2.6.1.85	Aminodeoxychorismate synthase
+2.6.1.86	2-amino-4-deoxychorismate synthase
+2.6.1.87	UDP-4-amino-4-deoxy-L-arabinose aminotransferase
+2.6.1.88	Methionine transaminase
+2.6.1.89	dTDP-3-amino-3,6-dideoxy-alpha-D-glucopyranose transaminase
+2.6.1.90	dTDP-3-amino-3,6-dideoxy-alpha-D-galactopyranose transaminase
+2.6.1.91	Transferred entry: 2.6.1.34
+2.6.1.92	UDP-4-amino-4,6-dideoxy-N-acetyl-beta-L-altrosamine transaminase
+2.6.1.93	Neamine transaminase
+2.6.1.94	2'-deamino-2'-hydroxyneamine transaminase
+2.6.1.95	Neomycin C transaminase
+2.6.1.96	4-aminobutyrate--pyruvate transaminase
+2.6.1.97	Archaeosine synthase
+2.6.1.98	UDP-2-acetamido-2-deoxy-ribo-hexuluronate aminotransferase
+2.6.1.99	L-tryptophan--pyruvate aminotransferase
+2.6.1.100	L-glutamine:2-deoxy-scyllo-inosose aminotransferase
+2.6.1.101	L-glutamine:3-amino-2,3-dideoxy-scyllo-inosose aminotransferase
+2.6.1.102	GDP-perosamine synthase
+2.6.1.103	(S)-3,5-dihydroxyphenylglycine transaminase
+2.6.1.104	3-dehydro-glucose-6-phosphate--glutamate transaminase
+2.6.1.105	Lysine--8-amino-7-oxononanoate transaminase
+2.6.1.106	dTDP-3-amino-3,4,6-trideoxy-alpha-D-glucose transaminase
+2.6.1.107	Beta-methylphenylalanine transaminase
+2.6.1.108	(5-formylfuran-3-yl)methyl phosphate transaminase
+2.6.1.109	8-amino-3,8-dideoxy-alpha-D-manno-octulosonate transaminase
+2.6.2.1	Transferred entry: 2.1.4.1
+2.6.3.1	Oximinotransferase
+2.6.99.1	dATP(dGTP)--DNA purinetransferase
+2.6.99.2	Pyridoxine 5'-phosphate synthase
+2.6.99.3	O-ureido-L-serine synthase
+2.6.99.4	Transferred entry: 2.3.1.234
+2.7.1.1	Hexokinase
+2.7.1.2	Glucokinase
+2.7.1.3	Ketohexokinase
+2.7.1.4	Fructokinase
+2.7.1.5	Rhamnulokinase
+2.7.1.6	Galactokinase
+2.7.1.7	Mannokinase
+2.7.1.8	Glucosamine kinase
+2.7.1.9	Deleted entry
+2.7.1.10	Phosphoglucokinase
+2.7.1.11	6-phosphofructokinase
+2.7.1.12	Gluconokinase
+2.7.1.13	Dehydrogluconokinase
+2.7.1.14	Sedoheptulokinase
+2.7.1.15	Ribokinase
+2.7.1.16	Ribulokinase
+2.7.1.17	Xylulokinase
+2.7.1.18	Phosphoribokinase
+2.7.1.19	Phosphoribulokinase
+2.7.1.20	Adenosine kinase
+2.7.1.21	Thymidine kinase
+2.7.1.22	Ribosylnicotinamide kinase
+2.7.1.23	NAD(+) kinase
+2.7.1.24	Dephospho-CoA kinase
+2.7.1.25	Adenylyl-sulfate kinase
+2.7.1.26	Riboflavin kinase
+2.7.1.27	Erythritol kinase
+2.7.1.28	Triokinase
+2.7.1.29	Glycerone kinase
+2.7.1.30	Glycerol kinase
+2.7.1.31	Glycerate 3-kinase
+2.7.1.32	Choline kinase
+2.7.1.33	Pantothenate kinase
+2.7.1.34	Pantetheine kinase
+2.7.1.35	Pyridoxal kinase
+2.7.1.36	Mevalonate kinase
+2.7.1.37	2.7.11.30 and 2.7.12.1
+2.7.1.38	Transferred entry: 2.7.11.19
+2.7.1.39	Homoserine kinase
+2.7.1.40	Pyruvate kinase
+2.7.1.41	Glucose-1-phosphate phosphodismutase
+2.7.1.42	Riboflavin phosphotransferase
+2.7.1.43	Glucuronokinase
+2.7.1.44	Galacturonokinase
+2.7.1.45	2-dehydro-3-deoxygluconokinase
+2.7.1.46	L-arabinokinase
+2.7.1.47	D-ribulokinase
+2.7.1.48	Uridine kinase
+2.7.1.49	Hydroxymethylpyrimidine kinase
+2.7.1.50	Hydroxyethylthiazole kinase
+2.7.1.51	L-fuculokinase
+2.7.1.52	Fucokinase
+2.7.1.53	L-xylulokinase
+2.7.1.54	D-arabinokinase
+2.7.1.55	Allose kinase
+2.7.1.56	1-phosphofructokinase
+2.7.1.57	Deleted entry
+2.7.1.58	2-dehydro-3-deoxygalactonokinase
+2.7.1.59	N-acetylglucosamine kinase
+2.7.1.60	N-acylmannosamine kinase
+2.7.1.61	Acyl-phosphate--hexose phosphotransferase
+2.7.1.62	Phosphoramidate--hexose phosphotransferase
+2.7.1.63	Polyphosphate--glucose phosphotransferase
+2.7.1.64	Inositol 3-kinase
+2.7.1.65	Scyllo-inosamine 4-kinase
+2.7.1.66	Undecaprenol kinase
+2.7.1.67	1-phosphatidylinositol 4-kinase
+2.7.1.68	1-phosphatidylinositol-4-phosphate 5-kinase
+2.7.1.69	Protein-N(pi)-phosphohistidine--sugar phosphotransferase
+2.7.1.70	Transferred entry: 2.7.11.1
+2.7.1.71	Shikimate kinase
+2.7.1.72	Streptomycin 6-kinase
+2.7.1.73	Inosine kinase
+2.7.1.74	Deoxycytidine kinase
+2.7.1.75	Transferred entry: 2.7.1.21
+2.7.1.76	Deoxyadenosine kinase
+2.7.1.77	Nucleoside phosphotransferase
+2.7.1.78	Polynucleotide 5'-hydroxyl-kinase
+2.7.1.79	Diphosphate--glycerol phosphotransferase
+2.7.1.80	Diphosphate--serine phosphotransferase
+2.7.1.81	Hydroxylysine kinase
+2.7.1.82	Ethanolamine kinase
+2.7.1.83	Pseudouridine kinase
+2.7.1.84	Alkylglycerone kinase
+2.7.1.85	Beta-glucoside kinase
+2.7.1.86	NADH kinase
+2.7.1.87	Streptomycin 3''-kinase
+2.7.1.88	Dihydrostreptomycin-6-phosphate 3'-alpha-kinase
+2.7.1.89	Thiamine kinase
+2.7.1.90	Diphosphate--fructose-6-phosphate 1-phosphotransferase
+2.7.1.91	Sphinganine kinase
+2.7.1.92	5-dehydro-2-deoxygluconokinase
+2.7.1.93	Alkylglycerol kinase
+2.7.1.94	Acylglycerol kinase
+2.7.1.95	Kanamycin kinase
+2.7.1.96	Transferred entry: 2.7.1.86
+2.7.1.97	Transferred entry: 2.7.11.14
+2.7.1.98	Deleted entry
+2.7.1.99	Transferred entry: 2.7.11.2
+2.7.1.100	S-methyl-5-thioribose kinase
+2.7.1.101	Tagatose kinase
+2.7.1.102	Hamamelose kinase
+2.7.1.103	Viomycin kinase
+2.7.1.104	Transferred entry: 2.7.99.1
+2.7.1.105	6-phosphofructo-2-kinase
+2.7.1.106	Glucose-1,6-bisphosphate synthase
+2.7.1.107	Diacylglycerol kinase (ATP)
+2.7.1.108	Dolichol kinase
+2.7.1.109	Transferred entry: 2.7.11.31
+2.7.1.110	Transferred entry: 2.7.11.3
+2.7.1.111	Transferred entry: 2.7.11.27
+2.7.1.112	Transferred entry: 2.7.10.1 and 2.7.10.2
+2.7.1.113	Deoxyguanosine kinase
+2.7.1.114	AMP--thymidine kinase
+2.7.1.115	Transferred entry: 2.7.11.4
+2.7.1.116	Transferred entry: 2.7.11.5
+2.7.1.117	Transferred entry: 2.7.11.18
+2.7.1.118	ADP--thymidine kinase
+2.7.1.119	Hygromycin-B 7''-O-kinase
+2.7.1.120	Transferred entry: 2.7.11.17
+2.7.1.121	Phosphoenolpyruvate--glycerone phosphotransferase
+2.7.1.122	Xylitol kinase
+2.7.1.123	Transferred entry: 2.7.11.17
+2.7.1.124	Transferred entry: 2.7.11.6
+2.7.1.125	Transferred entry: 2.7.11.14
+2.7.1.126	Transferred entry: 2.7.11.15
+2.7.1.127	Inositol-trisphosphate 3-kinase
+2.7.1.128	Transferred entry: 2.7.11.27
+2.7.1.129	Transferred entry: 2.7.11.7
+2.7.1.130	Tetraacyldisaccharide 4'-kinase
+2.7.1.131	Transferred entry: 2.7.11.29
+2.7.1.132	Transferred entry: 2.7.11.28
+2.7.1.133	Transferred entry: 2.7.1.134
+2.7.1.134	Inositol-tetrakisphosphate 1-kinase
+2.7.1.135	Transferred entry: 2.7.11.26
+2.7.1.136	Macrolide 2'-kinase
+2.7.1.137	Phosphatidylinositol 3-kinase
+2.7.1.138	Ceramide kinase
+2.7.1.139	Transferred entry: 2.7.1.134
+2.7.1.140	Inositol-tetrakisphosphate 5-kinase
+2.7.1.141	Transferred entry: 2.7.11.23
+2.7.1.142	Glycerol-3-phosphate--glucose phosphotransferase
+2.7.1.143	Diphosphate-purine nucleoside kinase
+2.7.1.144	Tagatose-6-phosphate kinase
+2.7.1.145	Deoxynucleoside kinase
+2.7.1.146	ADP-specific phosphofructokinase
+2.7.1.147	ADP-specific glucokinase
+2.7.1.148	4-(cytidine 5'-diphospho)-2-C-methyl-D-erythritol kinase
+2.7.1.149	1-phosphatidylinositol-5-phosphate 4-kinase
+2.7.1.150	1-phosphatidylinositol-3-phosphate 5-kinase
+2.7.1.151	Inositol-polyphosphate multikinase
+2.7.1.152	Transferred entry: 2.7.4.21
+2.7.1.153	Phosphatidylinositol-4,5-bisphosphate 3-kinase
+2.7.1.154	Phosphatidylinositol-4-phosphate 3-kinase
+2.7.1.155	Transferred entry: 2.7.4.24
+2.7.1.156	Adenosylcobinamide kinase
+2.7.1.157	N-acetylgalactosamine kinase
+2.7.1.158	Inositol-pentakisphosphate 2-kinase
+2.7.1.159	Inositol-1,3,4-trisphosphate 5/6-kinase
+2.7.1.160	2'-phosphotransferase
+2.7.1.161	CTP-dependent riboflavin kinase
+2.7.1.162	N-acetylhexosamine 1-kinase
+2.7.1.163	Hygromycin B 4-O-kinase
+2.7.1.164	O-phosphoseryl-tRNA(Sec) kinase
+2.7.1.165	Glycerate 2-kinase
+2.7.1.166	3-deoxy-D-manno-octulosonic acid kinase
+2.7.1.167	D-glycero-beta-D-manno-heptose-7-phosphate kinase
+2.7.1.168	D-glycero-alpha-D-manno-heptose-7-phosphate kinase
+2.7.1.169	Pantoate kinase
+2.7.1.170	Anhydro-N-acetylmuramic acid kinase
+2.7.1.171	Protein-fructosamine 3-kinase
+2.7.1.172	Protein-ribulosamine 3-kinase
+2.7.1.173	Nicotinate riboside kinase
+2.7.1.174	Diacylglycerol kinase (CTP)
+2.7.1.175	Maltokinase
+2.7.1.176	UDP-N-acetylglucosamine kinase
+2.7.1.177	L-threonine kinase
+2.7.1.178	2-dehydro-3-deoxyglucono/galactono-kinase
+2.7.1.179	Kanosamine kinase
+2.7.1.180	FAD:protein FMN transferase
+2.7.1.181	Polymannosyl GlcNAc-diphospho-ditrans,octacis-undecaprenol kinase
+2.7.1.182	Phytol kinase
+2.7.1.183	Glycoprotein-mannosyl O(6)-kinase
+2.7.1.184	Sulfofructose kinase
+2.7.1.185	Mevalonate 3-kinase
+2.7.1.186	Mevalonate-3-phosphate 5-kinase
+2.7.1.187	Acarbose 7(IV)-phosphotransferase
+2.7.1.188	2-epi-5-epi-valiolone 7-kinase
+2.7.1.189	Autoinducer-2 kinase
+2.7.1.190	Aminoglycoside 2''-phosphotransferase
+2.7.2.1	Acetate kinase
+2.7.2.2	Carbamate kinase
+2.7.2.3	Phosphoglycerate kinase
+2.7.2.4	Aspartate kinase
+2.7.2.5	Transferred entry: 6.3.4.16
+2.7.2.6	Formate kinase
+2.7.2.7	Butyrate kinase
+2.7.2.8	Acetylglutamate kinase
+2.7.2.9	Transferred entry: 6.3.5.5
+2.7.2.10	Phosphoglycerate kinase (GTP)
+2.7.2.11	Glutamate 5-kinase
+2.7.2.12	Acetate kinase (diphosphate)
+2.7.2.13	Glutamate 1-kinase
+2.7.2.14	Branched-chain-fatty-acid kinase
+2.7.2.15	Propionate kinase
+2.7.3.1	Guanidinoacetate kinase
+2.7.3.2	Creatine kinase
+2.7.3.3	Arginine kinase
+2.7.3.4	Taurocyamine kinase
+2.7.3.5	Lombricine kinase
+2.7.3.6	Hypotaurocyamine kinase
+2.7.3.7	Opheline kinase
+2.7.3.8	Ammonia kinase
+2.7.3.9	Phosphoenolpyruvate--protein phosphotransferase
+2.7.3.10	Agmatine kinase
+2.7.3.11	Transferred entry: 2.7.13.1
+2.7.3.12	Transferred entry: 2.7.13.2
+2.7.4.1	Polyphosphate kinase
+2.7.4.2	Phosphomevalonate kinase
+2.7.4.3	Adenylate kinase
+2.7.4.4	Nucleoside-phosphate kinase
+2.7.4.5	Transferred entry: 2.7.4.14
+2.7.4.6	Nucleoside-diphosphate kinase
+2.7.4.7	Phosphomethylpyrimidine kinase
+2.7.4.8	Guanylate kinase
+2.7.4.9	dTMP kinase
+2.7.4.10	Nucleoside-triphosphate--adenylate kinase
+2.7.4.11	(Deoxy)adenylate kinase
+2.7.4.12	T(2)-induced deoxynucleotide kinase
+2.7.4.13	(Deoxy)nucleoside-phosphate kinase
+2.7.4.14	UMP/CMP kinase
+2.7.4.15	Thiamine-diphosphate kinase
+2.7.4.16	Thiamine-phosphate kinase
+2.7.4.17	3-phosphoglyceroyl-phosphate--polyphosphate phosphotransferase
+2.7.4.18	Farnesyl-diphosphate kinase
+2.7.4.19	5-methyldeoxycytidine-5'-phosphate kinase
+2.7.4.20	Dolichyl-diphosphate--polyphosphate phosphotransferase
+2.7.4.21	Inositol-hexakisphosphate kinase
+2.7.4.22	UMP kinase
+2.7.4.23	Ribose 1,5-bisphosphate phosphokinase
+2.7.4.24	Diphosphoinositol-pentakisphosphate kinase
+2.7.4.25	(d)CMP kinase
+2.7.4.26	Isopentenyl phosphate kinase
+2.7.4.27	([Pyruvate, phosphate dikinase] phosphate) phosphotransferase
+2.7.4.28	([Pyruvate, water dikinase] phosphate) phosphotransferase
+2.7.4.29	Kdo(2)-lipid A phosphotransferase
+2.7.4.30	Lipid A phosphoethanolamine transferase
+2.7.4.31	(5-(aminomethyl)furan-3-yl)methyl phosphate kinase
+2.7.5.1	Transferred entry: 5.4.2.2
+2.7.5.2	Transferred entry: 5.4.2.3
+2.7.5.3	Transferred entry: 5.4.2.11 and 5.4.2.12
+2.7.5.4	Transferred entry: 5.4.2.4
+2.7.5.5	Transferred entry: 5.4.2.5
+2.7.5.6	Transferred entry: 5.4.2.7
+2.7.5.7	Transferred entry: 5.4.2.8
+2.7.6.1	Ribose-phosphate diphosphokinase
+2.7.6.2	Thiamine diphosphokinase
+2.7.6.3	2-amino-4-hydroxy-6-hydroxymethyldihydropteridine diphosphokinase
+2.7.6.4	Nucleotide diphosphokinase
+2.7.6.5	GTP diphosphokinase
+2.7.7.1	Nicotinamide-nucleotide adenylyltransferase
+2.7.7.2	FAD synthetase
+2.7.7.3	Pantetheine-phosphate adenylyltransferase
+2.7.7.4	Sulfate adenylyltransferase
+2.7.7.5	Sulfate adenylyltransferase (ADP)
+2.7.7.6	DNA-directed RNA polymerase
+2.7.7.7	DNA-directed DNA polymerase
+2.7.7.8	Polyribonucleotide nucleotidyltransferase
+2.7.7.9	UTP--glucose-1-phosphate uridylyltransferase
+2.7.7.10	UTP--hexose-1-phosphate uridylyltransferase
+2.7.7.11	UTP--xylose-1-phosphate uridylyltransferase
+2.7.7.12	UDP-glucose--hexose-1-phosphate uridylyltransferase
+2.7.7.13	Mannose-1-phosphate guanylyltransferase
+2.7.7.14	Ethanolamine-phosphate cytidylyltransferase
+2.7.7.15	Choline-phosphate cytidylyltransferase
+2.7.7.16	Transferred entry: 3.1.27.5
+2.7.7.17	Transferred entry: 3.1.27.1
+2.7.7.18	Nicotinate-nucleotide adenylyltransferase
+2.7.7.19	Polynucleotide adenylyltransferase
+2.7.7.20	Deleted entry
+2.7.7.21	Transferred entry: 2.7.7.72
+2.7.7.22	Mannose-1-phosphate guanylyltransferase (GDP)
+2.7.7.23	UDP-N-acetylglucosamine diphosphorylase
+2.7.7.24	Glucose-1-phosphate thymidylyltransferase
+2.7.7.25	Transferred entry: 2.7.7.72
+2.7.7.26	Transferred entry: 3.1.27.3
+2.7.7.27	Glucose-1-phosphate adenylyltransferase
+2.7.7.28	Nucleoside-triphosphate-aldose-1-phosphate nucleotidyltransferase
+2.7.7.29	Transferred entry: 2.7.7.28
+2.7.7.30	Fucose-1-phosphate guanylyltransferase
+2.7.7.31	DNA nucleotidylexotransferase
+2.7.7.32	Galactose-1-phosphate thymidylyltransferase
+2.7.7.33	Glucose-1-phosphate cytidylyltransferase
+2.7.7.34	Glucose-1-phosphate guanylyltransferase
+2.7.7.35	Ribose-5-phosphate adenylyltransferase
+2.7.7.36	Aldose-1-phosphate adenylyltransferase
+2.7.7.37	Aldose-1-phosphate nucleotidyltransferase
+2.7.7.38	3-deoxy-manno-octulosonate cytidylyltransferase
+2.7.7.39	Glycerol-3-phosphate cytidylyltransferase
+2.7.7.40	D-ribitol-5-phosphate cytidylyltransferase
+2.7.7.41	Phosphatidate cytidylyltransferase
+2.7.7.42	[Glutamate--ammonia-ligase] adenylyltransferase
+2.7.7.43	N-acylneuraminate cytidylyltransferase
+2.7.7.44	Glucuronate-1-phosphate uridylyltransferase
+2.7.7.45	Guanosine-triphosphate guanylyltransferase
+2.7.7.46	Gentamicin 2''-nucleotidyltransferase
+2.7.7.47	Streptomycin 3''-adenylyltransferase
+2.7.7.48	RNA-directed RNA polymerase
+2.7.7.49	RNA-directed DNA polymerase
+2.7.7.50	mRNA guanylyltransferase
+2.7.7.51	Adenylylsulfate--ammonia adenylyltransferase
+2.7.7.52	RNA uridylyltransferase
+2.7.7.53	ATP adenylyltransferase
+2.7.7.54	Transferred entry: 6.3.2.40
+2.7.7.55	Transferred entry: 6.3.2.40
+2.7.7.56	tRNA nucleotidyltransferase
+2.7.7.57	N-methylphosphoethanolamine cytidylyltransferase
+2.7.7.58	(2,3-dihydroxybenzoyl)adenylate synthase
+2.7.7.59	[Protein-PII] uridylyltransferase
+2.7.7.60	2-C-methyl-D-erythritol 4-phosphate cytidylyltransferase
+2.7.7.61	Citrate lyase holo-[acyl-carrier protein] synthase
+2.7.7.62	Adenosylcobinamide-phosphate guanylyltransferase
+2.7.7.63	Lipoate--protein ligase
+2.7.7.64	UTP-monosaccharide-1-phosphate uridylyltransferase
+2.7.7.65	Diguanylate cyclase
+2.7.7.66	Malonate decarboxylase holo-[acyl-carrier protein] synthase
+2.7.7.67	CDP-2,3-bis-(O-geranylgeranyl)-sn-glycerol synthase
+2.7.7.68	2-phospho-L-lactate guanylyltransferase
+2.7.7.69	GDP-L-galactose phosphorylase
+2.7.7.70	D-glycero-beta-D-manno-heptose 1-phosphate adenylyltransferase
+2.7.7.71	D-glycero-alpha-D-manno-heptose 1-phosphate guanylyltransferase
+2.7.7.72	CCA tRNA nucleotidyltransferase
+2.7.7.73	Sulfur carrier protein ThiS adenylyltransferase
+2.7.7.74	1L-myo-inositol 1-phosphate cytidylyltransferase
+2.7.7.75	Molybdopterin adenylyltransferase
+2.7.7.76	Molybdenum cofactor cytidylyltransferase
+2.7.7.77	Molybdenum cofactor guanylyltransferase
+2.7.7.78	GDP-D-glucose phosphorylase
+2.7.7.79	tRNA(His) guanylyltransferase
+2.7.7.80	Molybdopterin-synthase adenylyltransferase
+2.7.7.81	Pseudaminic acid cytidylyltransferase
+2.7.7.82	CMP-N,N'-diacetyllegionaminic acid synthase
+2.7.7.83	UDP-N-acetylgalactosamine diphosphorylase
+2.7.7.84	2'-5' oligoadenylate synthase
+2.7.7.85	Diadenylate cyclase
+2.7.7.86	Cyclic GMP-AMP synthase
+2.7.7.87	L-threonylcarbamoyladenylate synthase
+2.7.7.88	GDP polyribonucleotidyltransferase
+2.7.7.89	[Glutamate--ammonia ligase]-adenylyl-L-tyrosine phosphorylase
+2.7.8.1	Ethanolaminephosphotransferase
+2.7.8.2	Diacylglycerol cholinephosphotransferase
+2.7.8.3	Ceramide cholinephosphotransferase
+2.7.8.4	Serine-phosphoethanolamine synthase
+2.7.8.5	CDP-diacylglycerol--glycerol-3-phosphate 3-phosphatidyltransferase
+2.7.8.6	Undecaprenyl-phosphate galactose phosphotransferase
+2.7.8.7	Holo-[acyl-carrier-protein] synthase
+2.7.8.8	CDP-diacylglycerol--serine O-phosphatidyltransferase
+2.7.8.9	Phosphomannan mannosephosphotransferase
+2.7.8.10	Sphingosine cholinephosphotransferase
+2.7.8.11	CDP-diacylglycerol--inositol 3-phosphatidyltransferase
+2.7.8.12	CDP-glycerol glycerophosphotransferase
+2.7.8.13	Phospho-N-acetylmuramoyl-pentapeptide-transferase
+2.7.8.14	CDP-ribitol ribitolphosphotransferase
+2.7.8.15	N-acetylglucosaminephosphotransferase
+2.7.8.16	Transferred entry: 2.7.8.2
+2.7.8.17	N-acetylglucosaminephosphotransferase
+2.7.8.18	UDP-galactose--UDP-N-acetylglucosamine galactose phosphotransferase
+2.7.8.19	UDP-glucose--glycoprotein glucose phosphotransferase
+2.7.8.20	Phosphatidylglycerol--membrane-oligosaccharide glycerophosphotransferase
+2.7.8.21	Membrane-oligosaccharide glycerophosphotransferase
+2.7.8.22	1-alkenyl-2-acylglycerol choline phosphotransferase
+2.7.8.23	Carboxyvinyl-carboxyphosphonate phosphorylmutase
+2.7.8.24	Phosphatidylcholine synthase
+2.7.8.25	Transferred entry: 2.4.2.52
+2.7.8.26	Adenosylcobinamide-GDP ribazoletransferase
+2.7.8.27	Sphingomyelin synthase
+2.7.8.28	2-phospho-L-lactate transferase
+2.7.8.29	L-serine-phosphatidylethanolamine phosphatidyltransferase
+2.7.8.30	Transferred entry: 2.4.2.53
+2.7.8.31	Undecaprenyl-phosphate glucose phosphotransferase
+2.7.8.32	xylosylphosphotransferase
+2.7.8.33	N-acetylglucosaminephosphotransferase
+2.7.8.34	CDP-L-myo-inositol myo-inositolphosphotransferase
+2.7.8.35	N-acetylglucosaminephosphotransferase
+2.7.8.36	transferase
+2.7.8.37	Alpha-D-ribose 1-methylphosphonate 5-triphosphate synthase
+2.7.8.38	Archaetidylserine synthase
+2.7.8.39	Archaetidylinositol phosphate synthase
+2.7.8.40	N-acetylgalactosaminephosphotransferase
+2.7.8.41	Cardiolipin synthase (CMP-forming)
+2.7.8.42	Kdo(2)-lipid A phosphoethanolamine 7''-transferase
+2.7.9.1	Pyruvate, phosphate dikinase
+2.7.9.2	Pyruvate, water dikinase
+2.7.9.3	Selenide, water dikinase
+2.7.9.4	Alpha-glucan, water dikinase
+2.7.9.5	Phosphoglucan, water dikinase
+2.7.10.1	Receptor protein-tyrosine kinase
+2.7.10.2	Non-specific protein-tyrosine kinase
+2.7.11.1	Non-specific serine/threonine protein kinase
+2.7.11.2	[Pyruvate dehydrogenase (acetyl-transferring)] kinase
+2.7.11.3	Dephospho-[reductase kinase] kinase
+2.7.11.4	[3-methyl-2-oxobutanoate dehydrogenase (acetyl-transferring)] kinase
+2.7.11.5	[Isocitrate dehydrogenase (NADP(+))] kinase
+2.7.11.6	[Tyrosine 3-monooxygenase] kinase
+2.7.11.7	[Myosin heavy-chain] kinase
+2.7.11.8	Fas-activated serine/threonine kinase
+2.7.11.9	[Goodpasture-antigen-binding protein] kinase
+2.7.11.10	I-kappa-B kinase
+2.7.11.11	cAMP-dependent protein kinase
+2.7.11.12	cGMP-dependent protein kinase
+2.7.11.13	Protein kinase C
+2.7.11.14	Rhodopsin kinase
+2.7.11.15	[Beta-adrenergic-receptor] kinase
+2.7.11.16	[G-protein-coupled receptor] kinase
+2.7.11.17	Calcium/calmodulin-dependent protein kinase
+2.7.11.18	[Myosin light-chain] kinase
+2.7.11.19	Phosphorylase kinase
+2.7.11.20	[Elongation factor 2] kinase
+2.7.11.21	Polo kinase
+2.7.11.22	Cyclin-dependent kinase
+2.7.11.23	[RNA-polymerase]-subunit kinase
+2.7.11.24	Mitogen-activated protein kinase
+2.7.11.25	Mitogen-activated protein kinase kinase kinase
+2.7.11.26	[Tau protein] kinase
+2.7.11.27	[Acetyl-CoA carboxylase] kinase
+2.7.11.28	Tropomyosin kinase
+2.7.11.29	[Low-density-lipoprotein receptor] kinase
+2.7.11.30	Receptor protein serine/threonine kinase
+2.7.11.31	[Hydroxymethylglutaryl-CoA reductase (NADPH)] kinase
+2.7.11.32	[Pyruvate, phosphate dikinase] kinase
+2.7.11.33	[Pyruvate, water dikinase] kinase
+2.7.12.1	Dual-specificity kinase
+2.7.12.2	Mitogen-activated protein kinase kinase
+2.7.13.1	Protein-histidine pros-kinase
+2.7.13.2	Protein-histidine tele-kinase
+2.7.13.3	Histidine kinase
+2.7.14.1	Protein arginine kinase
+2.7.99.1	Triphosphate--protein phosphotransferase
+2.8.1.1	Thiosulfate sulfurtransferase
+2.8.1.2	3-mercaptopyruvate sulfurtransferase
+2.8.1.3	Thiosulfate--thiol sulfurtransferase
+2.8.1.4	tRNA sulfurtransferase
+2.8.1.5	Thiosulfate--dithiol sulfurtransferase
+2.8.1.6	Biotin synthase
+2.8.1.7	Cysteine desulfurase
+2.8.1.8	Lipoyl synthase
+2.8.1.9	Molybdenum cofactor sulfurtransferase
+2.8.1.10	Thiazole synthase
+2.8.1.11	Molybdopterin-synthase sulfurtransferase
+2.8.1.12	Molybdopterin synthase
+2.8.1.13	tRNA-uridine 2-sulfurtransferase
+2.8.1.14	tRNA-5-taurinomethyluridine 2-sulfurtransferase
+2.8.2.1	Aryl sulfotransferase
+2.8.2.2	Alcohol sulfotransferase
+2.8.2.3	Amine sulfotransferase
+2.8.2.4	Estrone sulfotransferase
+2.8.2.5	Chondroitin 4-sulfotransferase
+2.8.2.6	Choline sulfotransferase
+2.8.2.7	UDP-N-acetylgalactosamine-4-sulfate sulfotransferase
+2.8.2.8	[Heparan sulfate]-glucosamine N-sulfotransferase
+2.8.2.9	Tyrosine-ester sulfotransferase
+2.8.2.10	Renilla-luciferin sulfotransferase
+2.8.2.11	Galactosylceramide sulfotransferase
+2.8.2.12	Transferred entry: 2.8.2.8
+2.8.2.13	Psychosine sulfotransferase
+2.8.2.14	Bile-salt sulfotransferase
+2.8.2.15	Steroid sulfotransferase
+2.8.2.16	Thiol sulfotransferase
+2.8.2.17	Chondroitin 6-sulfotransferase
+2.8.2.18	Cortisol sulfotransferase
+2.8.2.19	Triglucosylalkylacylglycerol sulfotransferase
+2.8.2.20	Protein-tyrosine sulfotransferase
+2.8.2.21	Keratan sulfotransferase
+2.8.2.22	Aryl-sulfate sulfotransferase
+2.8.2.23	[Heparan sulfate]-glucosamine 3-sulfotransferase 1
+2.8.2.24	Desulfoglucosinolate sulfotransferase
+2.8.2.25	Flavonol 3-sulfotransferase
+2.8.2.26	Quercetin-3-sulfate 3'-sulfotransferase
+2.8.2.27	Quercetin-3-sulfate 4'-sulfotransferase
+2.8.2.28	Quercetin-3,3'-bissulfate 7-sulfotransferase
+2.8.2.29	[Heparan sulfate]-glucosamine 3-sulfotransferase 2
+2.8.2.30	[Heparan sulfate]-glucosamine 3-sulfotransferase 3
+2.8.2.31	Petromyzonol sulfotransferase
+2.8.2.32	Scymnol sulfotransferase
+2.8.2.33	N-acetylgalactosamine 4-sulfate 6-O-sulfotransferase
+2.8.2.34	Glycochenodeoxycholate sulfotransferase
+2.8.2.35	Dermatan 4-sulfotransferase
+2.8.2.36	Desulfo-A47934 sulfotransferase
+2.8.2.37	Trehalose 2-sulfotransferase
+2.8.3.1	Propionate CoA-transferase
+2.8.3.2	Oxalate CoA-transferase
+2.8.3.3	Malonate CoA-transferase
+2.8.3.4	Deleted entry
+2.8.3.5	3-oxoacid CoA-transferase
+2.8.3.6	3-oxoadipate CoA-transferase
+2.8.3.7	Deleted entry
+2.8.3.8	Acetate CoA-transferase
+2.8.3.9	Butyrate--acetoacetate CoA-transferase
+2.8.3.10	Citrate CoA-transferase
+2.8.3.11	Citramalate CoA-transferase
+2.8.3.12	Glutaconate CoA-transferase
+2.8.3.13	Succinate--hydroxymethylglutarate CoA-transferase
+2.8.3.14	5-hydroxypentanoate CoA-transferase
+2.8.3.15	Succinyl-CoA:(R)-benzylsuccinate CoA-transferase
+2.8.3.16	Formyl-CoA transferase
+2.8.3.17	Cinnamoyl-CoA:phenyllactate CoA-transferase
+2.8.3.18	Succinyl-CoA:acetate CoA-transferase
+2.8.3.19	CoA:oxalate CoA-transferase
+2.8.3.20	Succinyl-CoA--D-citramalate CoA-transferase
+2.8.3.21	L-carnitine CoA-transferase
+2.8.3.22	Succinyl-CoA--L-malate CoA-transferase
+2.8.3.23	Caffeate CoA-transferase
+2.8.4.1	Coenzyme-B sulfoethylthiotransferase
+2.8.4.2	Arsenate-mycothiol transferase
+2.8.4.3	tRNA-2-methylthio-N(6)-dimethylallyladenosine synthase
+2.8.4.4	[Ribosomal protein S12] (aspartate(89)-C(3))-methylthiotransferase
+2.8.4.5	tRNA (N(6)-L-threonylcarbamoyladenosine(37)-C(2))-methylthiotransferase
+2.9.1.1	L-seryl-tRNA(Sec) selenium transferase
+2.9.1.2	O-phospho-L-seryl-tRNA(Sec):L-selenocysteinyl-tRNA synthase
+2.10.1.1	Molybdopterin molybdotransferase
+3.1.1.1	Carboxylesterase
+3.1.1.2	Arylesterase
+3.1.1.3	Triacylglycerol lipase
+3.1.1.4	Phospholipase A(2)
+3.1.1.5	Lysophospholipase
+3.1.1.6	Acetylesterase
+3.1.1.7	Acetylcholinesterase
+3.1.1.8	Cholinesterase
+3.1.1.9	Deleted entry
+3.1.1.10	Tropinesterase
+3.1.1.11	Pectinesterase
+3.1.1.12	Transferred entry: 3.1.1.1
+3.1.1.13	Sterol esterase
+3.1.1.14	Chlorophyllase
+3.1.1.15	L-arabinonolactonase
+3.1.1.16	Transferred entry: 3.1.1.24 and 5.3.3.4
+3.1.1.17	Gluconolactonase
+3.1.1.18	Transferred entry: 3.1.1.17
+3.1.1.19	Uronolactonase
+3.1.1.20	Tannase
+3.1.1.21	Deleted entry
+3.1.1.22	Hydroxybutyrate-dimer hydrolase
+3.1.1.23	Acylglycerol lipase
+3.1.1.24	3-oxoadipate enol-lactonase
+3.1.1.25	1,4-lactonase
+3.1.1.26	Galactolipase
+3.1.1.27	4-pyridoxolactonase
+3.1.1.28	Acylcarnitine hydrolase
+3.1.1.29	Aminoacyl-tRNA hydrolase
+3.1.1.30	D-arabinonolactonase
+3.1.1.31	6-phosphogluconolactonase
+3.1.1.32	Phospholipase A(1)
+3.1.1.33	6-acetylglucose deacetylase
+3.1.1.34	Lipoprotein lipase
+3.1.1.35	Dihydrocoumarin hydrolase
+3.1.1.36	Limonin-D-ring-lactonase
+3.1.1.37	Steroid-lactonase
+3.1.1.38	Triacetate-lactonase
+3.1.1.39	Actinomycin lactonase
+3.1.1.40	Orsellinate-depside hydrolase
+3.1.1.41	Cephalosporin-C deacetylase
+3.1.1.42	Chlorogenate hydrolase
+3.1.1.43	Alpha-amino-acid esterase
+3.1.1.44	4-methyloxaloacetate esterase
+3.1.1.45	Carboxymethylenebutenolidase
+3.1.1.46	Deoxylimonate A-ring-lactonase
+3.1.1.47	1-alkyl-2-acetylglycerophosphocholine esterase
+3.1.1.48	Fusarinine-C ornithinesterase
+3.1.1.49	Sinapine esterase
+3.1.1.50	Wax-ester hydrolase
+3.1.1.51	Phorbol-diester hydrolase
+3.1.1.52	Phosphatidylinositol deacylase
+3.1.1.53	Sialate O-acetylesterase
+3.1.1.54	Acetoxybutynylbithiophene deacetylase
+3.1.1.55	Acetylsalicylate deacetylase
+3.1.1.56	Methylumbelliferyl-acetate deacetylase
+3.1.1.57	2-pyrone-4,6-dicarboxylate lactonase
+3.1.1.58	N-acetylgalactosaminoglycan deacetylase
+3.1.1.59	Juvenile-hormone esterase
+3.1.1.60	Bis(2-ethylhexyl)phthalate esterase
+3.1.1.61	Protein-glutamate methylesterase
+3.1.1.62	Transferred entry: 3.5.1.47
+3.1.1.63	11-cis-retinyl-palmitate hydrolase
+3.1.1.64	Retinoid isomerohydrolase
+3.1.1.65	L-rhamnono-1,4-lactonase
+3.1.1.66	5-(3,4-diacetoxybut-1-ynyl)-2,2'-bithiophene deacetylase
+3.1.1.67	Fatty-acyl-ethyl-ester synthase
+3.1.1.68	Xylono-1,4-lactonase
+3.1.1.69	Transferred entry: 3.5.1.89
+3.1.1.70	Cetraxate benzylesterase
+3.1.1.71	Acetylalkylglycerol acetylhydrolase
+3.1.1.72	Acetylxylan esterase
+3.1.1.73	Feruloyl esterase
+3.1.1.74	Cutinase
+3.1.1.75	Poly(3-hydroxybutyrate) depolymerase
+3.1.1.76	Poly(3-hydroxyoctanoate) depolymerase
+3.1.1.77	Acyloxyacyl hydrolase
+3.1.1.78	Polyneuridine-aldehyde esterase
+3.1.1.79	Hormone-sensitive lipase
+3.1.1.80	Acetylajmaline esterase
+3.1.1.81	Quorum-quenching N-acyl-homoserine lactonase
+3.1.1.82	Pheophorbidase
+3.1.1.83	Monoterpene epsilon-lactone hydrolase
+3.1.1.84	Cocaine esterase
+3.1.1.85	Pimeloyl-[acyl-carrier protein] methyl ester esterase
+3.1.1.86	Rhamnogalacturonan acetylesterase
+3.1.1.87	Fumonisin B1 esterase
+3.1.1.88	Pyrethroid hydrolase
+3.1.1.89	Protein phosphatase methylesterase-1
+3.1.1.90	All-trans-retinyl ester 13-cis isomerohydrolase
+3.1.1.91	2-oxo-3-(5-oxofuran-2-ylidene)propanoate lactonase
+3.1.1.92	4-sulfomuconolactone hydrolase
+3.1.1.93	Mycophenolic acid acyl-glucuronide esterase
+3.1.1.94	Versiconal hemiacetal acetate esterase
+3.1.1.95	Aclacinomycin methylesterase
+3.1.1.96	D-aminoacyl-tRNA deacylase
+3.1.1.97	Methylated diphthine methylhydrolase
+3.1.1.98	[Wnt protein] O-palmitoleoyl-L-serine hydrolase
+3.1.2.1	Acetyl-CoA hydrolase
+3.1.2.2	Palmitoyl-CoA hydrolase
+3.1.2.3	Succinyl-CoA hydrolase
+3.1.2.4	3-hydroxyisobutyryl-CoA hydrolase
+3.1.2.5	Hydroxymethylglutaryl-CoA hydrolase
+3.1.2.6	Hydroxyacylglutathione hydrolase
+3.1.2.7	Glutathione thiolesterase
+3.1.2.8	Transferred entry: 3.1.2.6
+3.1.2.9	Deleted entry
+3.1.2.10	Formyl-CoA hydrolase
+3.1.2.11	Acetoacetyl-CoA hydrolase
+3.1.2.12	S-formylglutathione hydrolase
+3.1.2.13	S-succinylglutathione hydrolase
+3.1.2.14	Oleoyl-[acyl-carrier-protein] hydrolase
+3.1.2.15	Deleted entry
+3.1.2.16	Citrate-lyase deacetylase
+3.1.2.17	(S)-methylmalonyl-CoA hydrolase
+3.1.2.18	ADP-dependent short-chain-acyl-CoA hydrolase
+3.1.2.19	ADP-dependent medium-chain-acyl-CoA hydrolase
+3.1.2.20	Acyl-CoA hydrolase
+3.1.2.21	Dodecanoyl-[acyl-carrier-protein] hydrolase
+3.1.2.22	Palmitoyl-protein hydrolase
+3.1.2.23	4-hydroxybenzoyl-CoA thioesterase
+3.1.2.24	Transferred entry: 3.13.1.3
+3.1.2.25	Phenylacetyl-CoA hydrolase
+3.1.2.26	Bile-acid-CoA hydrolase
+3.1.2.27	Choloyl-CoA hydrolase
+3.1.2.28	1,4-dihydroxy-2-naphthoyl-CoA hydrolase
+3.1.2.29	Fluoroacetyl-CoA thioesterase
+3.1.2.30	(3S)-malyl-CoA thioesterase
+3.1.2.31	Dihydromonacolin L-[lovastatin nonaketide synthase] thioesterase
+3.1.3.1	Alkaline phosphatase
+3.1.3.2	Acid phosphatase
+3.1.3.3	Phosphoserine phosphatase
+3.1.3.4	Phosphatidate phosphatase
+3.1.3.5	5'-nucleotidase
+3.1.3.6	3'-nucleotidase
+3.1.3.7	3'(2'),5'-bisphosphate nucleotidase
+3.1.3.8	3-phytase
+3.1.3.9	Glucose-6-phosphatase
+3.1.3.10	Glucose-1-phosphatase
+3.1.3.11	Fructose-bisphosphatase
+3.1.3.12	Trehalose-phosphatase
+3.1.3.13	Bisphosphoglycerate phosphatase
+3.1.3.14	Methylphosphothioglycerate phosphatase
+3.1.3.15	Histidinol-phosphatase
+3.1.3.16	Protein-serine/threonine phosphatase
+3.1.3.17	[Phosphorylase] phosphatase
+3.1.3.18	Phosphoglycolate phosphatase
+3.1.3.19	Glycerol-2-phosphatase
+3.1.3.20	Phosphoglycerate phosphatase
+3.1.3.21	Glycerol-1-phosphatase
+3.1.3.22	Mannitol-1-phosphatase
+3.1.3.23	Sugar-phosphatase
+3.1.3.24	Sucrose-phosphate phosphatase
+3.1.3.25	Inositol-phosphate phosphatase
+3.1.3.26	4-phytase
+3.1.3.27	Phosphatidylglycerophosphatase
+3.1.3.28	ADP-phosphoglycerate phosphatase
+3.1.3.29	N-acylneuraminate-9-phosphatase
+3.1.3.30	Transferred entry: 3.1.3.31
+3.1.3.31	Nucleotidase
+3.1.3.32	Polynucleotide 3'-phosphatase
+3.1.3.33	Polynucleotide 5'-phosphatase
+3.1.3.34	Deoxynucleotide 3'-phosphatase
+3.1.3.35	Thymidylate 5'-phosphatase
+3.1.3.36	Phosphoinositide 5-phosphatase
+3.1.3.37	Sedoheptulose-bisphosphatase
+3.1.3.38	3-phosphoglycerate phosphatase
+3.1.3.39	Streptomycin-6-phosphatase
+3.1.3.40	Guanidinodeoxy-scyllo-inositol-4-phosphatase
+3.1.3.41	4-nitrophenylphosphatase
+3.1.3.42	[Glycogen-synthase-D] phosphatase
+3.1.3.43	[Pyruvate dehydrogenase (acetyl-transferring)]-phosphatase
+3.1.3.44	[Acetyl-CoA carboxylase]-phosphatase
+3.1.3.45	3-deoxy-manno-octulosonate-8-phosphatase
+3.1.3.46	Fructose-2,6-bisphosphate 2-phosphatase
+3.1.3.47	[Hydroxymethylglutaryl-CoA reductase (NADPH)]-phosphatase
+3.1.3.48	Protein-tyrosine-phosphatase
+3.1.3.49	[Pyruvate kinase]-phosphatase
+3.1.3.50	Sorbitol-6-phosphatase
+3.1.3.51	Dolichyl-phosphatase
+3.1.3.52	phosphatase
+3.1.3.53	[Myosin-light-chain] phosphatase
+3.1.3.54	Fructose-2,6-bisphosphate 6-phosphatase
+3.1.3.55	Caldesmon-phosphatase
+3.1.3.56	Inositol-polyphosphate 5-phosphatase
+3.1.3.57	Inositol-1,4-bisphosphate 1-phosphatase
+3.1.3.58	Sugar-terminal-phosphatase
+3.1.3.59	Alkylacetylglycerophosphatase
+3.1.3.60	Phosphoenolpyruvate phosphatase
+3.1.3.61	Deleted entry
+3.1.3.62	Multiple inositol-polyphosphate phosphatase
+3.1.3.63	2-carboxy-D-arabinitol-1-phosphatase
+3.1.3.64	Phosphatidylinositol-3-phosphatase
+3.1.3.65	Transferred entry: 3.1.3.64
+3.1.3.66	Phosphatidylinositol-3,4-bisphosphate 4-phosphatase
+3.1.3.67	Phosphatidylinositol-3,4,5-trisphosphate 3-phosphatase
+3.1.3.68	2-deoxyglucose-6-phosphatase
+3.1.3.69	Glucosylglycerol 3-phosphatase
+3.1.3.70	Mannosyl-3-phosphoglycerate phosphatase
+3.1.3.71	2-phosphosulfolactate phosphatase
+3.1.3.72	5-phytase
+3.1.3.73	Adenosylcobalamin/alpha-ribazole phosphatase
+3.1.3.74	Pyridoxal phosphatase
+3.1.3.75	Phosphoethanolamine/phosphocholine phosphatase
+3.1.3.76	Lipid-phosphate phosphatase
+3.1.3.77	Acireductone synthase
+3.1.3.78	Phosphatidylinositol-4,5-bisphosphate 4-phosphatase
+3.1.3.79	Mannosylfructose-phosphate phosphatase
+3.1.3.80	2,3-bisphosphoglycerate 3-phosphatase
+3.1.3.81	Diacylglycerol diphosphate phosphatase
+3.1.3.82	D-glycero-beta-D-manno-heptose 1,7-bisphosphate 7-phosphatase
+3.1.3.83	D-glycero-alpha-D-manno-heptose-1,7-bisphosphate 7-phosphatase
+3.1.3.84	ADP-ribose 1''-phosphate phosphatase
+3.1.3.85	Glucosyl-3-phosphoglycerate phosphatase
+3.1.3.86	Phosphatidylinositol-3,4,5-trisphosphate 5-phosphatase
+3.1.3.87	2-hydroxy-3-keto-5-methylthiopentenyl-1-phosphate phosphatase
+3.1.3.88	5''-phosphoribostamycin phosphatase
+3.1.3.89	5'-deoxynucleotidase
+3.1.3.90	Maltose 6'-phosphate phosphatase
+3.1.3.91	7-methylguanosine nucleotidase
+3.1.3.92	Kanosamine-6-phosphate phosphatase
+3.1.3.93	L-galactose 1-phosphate phosphatase
+3.1.3.94	D-galactose 1-phosphate phosphatase
+3.1.3.95	Phosphatidylinositol-3,5-bisphosphate 3-phosphatase
+3.1.3.96	Pseudouridine 5'-phosphatase
+3.1.3.97	3',5'-nucleoside bisphosphate phosphatase
+3.1.3.98	Geranyl diphosphate phosphohydrolase
+3.1.4.1	Phosphodiesterase I
+3.1.4.2	Glycerophosphocholine phosphodiesterase
+3.1.4.3	Phospholipase C
+3.1.4.4	Phospholipase D
+3.1.4.5	Transferred entry: 3.1.21.1
+3.1.4.6	Transferred entry: 3.1.22.1
+3.1.4.7	Transferred entry: 3.1.31.1
+3.1.4.8	Transferred entry: 3.1.27.3
+3.1.4.9	Transferred entry: 3.1.30.2
+3.1.4.10	Transferred entry: 4.6.1.13
+3.1.4.11	Phosphoinositide phospholipase C
+3.1.4.12	Sphingomyelin phosphodiesterase
+3.1.4.13	Serine-ethanolaminephosphate phosphodiesterase
+3.1.4.14	[Acyl-carrier-protein] phosphodiesterase
+3.1.4.15	Transferred entry: 2.7.7.89
+3.1.4.16	2',3'-cyclic-nucleotide 2'-phosphodiesterase
+3.1.4.17	3',5'-cyclic-nucleotide phosphodiesterase
+3.1.4.18	Transferred entry: 3.1.16.1
+3.1.4.19	Transferred entry: 3.1.13.3
+3.1.4.20	Transferred entry: 3.1.13.1
+3.1.4.21	Transferred entry: 3.1.30.1
+3.1.4.22	Transferred entry: 3.1.27.5
+3.1.4.23	Transferred entry: 3.1.27.1
+3.1.4.24	Deleted entry
+3.1.4.25	Transferred entry: 3.1.11.1
+3.1.4.26	Deleted entry
+3.1.4.27	Transferred entry: 3.1.11.2
+3.1.4.28	Transferred entry: 3.1.11.3
+3.1.4.29	Deleted entry
+3.1.4.30	Transferred entry: 3.1.21.2
+3.1.4.31	Transferred entry: 3.1.11.4
+3.1.4.32	Deleted entry
+3.1.4.33	Deleted entry
+3.1.4.34	Deleted entry
+3.1.4.35	3',5'-cyclic-GMP phosphodiesterase
+3.1.4.36	Transferred entry: 3.1.4.43
+3.1.4.37	2',3'-cyclic-nucleotide 3'-phosphodiesterase
+3.1.4.38	Glycerophosphocholine cholinephosphodiesterase
+3.1.4.39	Alkylglycerophosphoethanolamine phosphodiesterase
+3.1.4.40	CMP-N-acylneuraminate phosphodiesterase
+3.1.4.41	Sphingomyelin phosphodiesterase D
+3.1.4.42	Glycerol-1,2-cyclic-phosphate 2-phosphodiesterase
+3.1.4.43	Glycerophosphoinositol inositolphosphodiesterase
+3.1.4.44	Glycerophosphoinositol glycerophosphodiesterase
+3.1.4.45	N-acetylglucosamine-1-phosphodiester alpha-N-acetylglucosaminidase
+3.1.4.46	Glycerophosphodiester phosphodiesterase
+3.1.4.47	Transferred entry: 4.6.1.14
+3.1.4.48	Dolichylphosphate-glucose phosphodiesterase
+3.1.4.49	Dolichylphosphate-mannose phosphodiesterase
+3.1.4.50	Glycosylphosphatidylinositol phospholipase D
+3.1.4.51	Glucose-1-phospho-D-mannosylglycoprotein phosphodiesterase
+3.1.4.52	Cyclic-guanylate-specific phosphodiesterase
+3.1.4.53	3',5'-cyclic-AMP phosphodiesterase
+3.1.4.54	N-acetylphosphatidylethanolamine-hydrolyzing phospholipase D
+3.1.4.55	Phosphoribosyl 1,2-cyclic phosphate phosphodiesterase
+3.1.4.56	7,8-dihydroneopterin 2',3'-cyclic phosphate phosphodiesterase
+3.1.4.57	Phosphoribosyl 1,2-cyclic phosphate 1,2-diphosphodiesterase
+3.1.5.1	dGTPase
+3.1.6.1	Arylsulfatase
+3.1.6.2	Steryl-sulfatase
+3.1.6.3	Glycosulfatase
+3.1.6.4	N-acetylgalactosamine-6-sulfatase
+3.1.6.5	Deleted entry
+3.1.6.6	Choline-sulfatase
+3.1.6.7	Cellulose-polysulfatase
+3.1.6.8	Cerebroside-sulfatase
+3.1.6.9	Chondro-4-sulfatase
+3.1.6.10	Chondro-6-sulfatase
+3.1.6.11	Disulfoglucosamine-6-sulfatase
+3.1.6.12	N-acetylgalactosamine-4-sulfatase
+3.1.6.13	Iduronate-2-sulfatase
+3.1.6.14	N-acetylglucosamine-6-sulfatase
+3.1.6.15	N-sulfoglucosamine-3-sulfatase
+3.1.6.16	Monomethyl-sulfatase
+3.1.6.17	D-lactate-2-sulfatase
+3.1.6.18	Glucuronate-2-sulfatase
+3.1.6.19	(R)-specific secondary-alkylsulfatase
+3.1.7.1	Prenyl-diphosphatase
+3.1.7.2	Guanosine-3',5'-bis(diphosphate) 3'-diphosphatase
+3.1.7.3	Monoterpenyl-diphosphatase
+3.1.7.4	Transferred entry: 4.2.1.133 and 4.2.3.141
+3.1.7.5	Geranylgeranyl diphosphate diphosphatase
+3.1.7.6	Farnesyl diphosphatase
+3.1.7.7	Drimenol cyclase
+3.1.7.8	Tuberculosinol synthase
+3.1.7.9	Isotuberculosinol synthase
+3.1.7.10	(13E)-labda-7,13-dien-15-ol synthase
+3.1.7.11	Geranyl diphosphate diphosphatase
+3.1.8.1	Aryldialkylphosphatase
+3.1.8.2	Diisopropyl-fluorophosphatase
+3.1.11.1	Exodeoxyribonuclease I
+3.1.11.2	Exodeoxyribonuclease III
+3.1.11.3	Exodeoxyribonuclease (lambda-induced)
+3.1.11.4	Exodeoxyribonuclease (phage SP3-induced)
+3.1.11.5	Exodeoxyribonuclease V
+3.1.11.6	Exodeoxyribonuclease VII
+3.1.12.1	5' to 3' exodeoxyribonuclease (nucleoside 3'-phosphate-forming)
+3.1.13.1	Exoribonuclease II
+3.1.13.2	Exoribonuclease H
+3.1.13.3	Oligonucleotidase
+3.1.13.4	Poly(A)-specific ribonuclease
+3.1.13.5	Ribonuclease D
+3.1.14.1	Yeast ribonuclease
+3.1.15.1	Venom exonuclease
+3.1.16.1	Spleen exonuclease
+3.1.21.1	Deoxyribonuclease I
+3.1.21.2	Deoxyribonuclease IV
+3.1.21.3	Type I site-specific deoxyribonuclease
+3.1.21.4	Type II site-specific deoxyribonuclease
+3.1.21.5	Type III site-specific deoxyribonuclease
+3.1.21.6	CC-preferring endodeoxyribonuclease
+3.1.21.7	Deoxyribonuclease V
+3.1.21.8	T(4) deoxyribonuclease II
+3.1.21.9	T(4) deoxyribonuclease IV
+3.1.22.1	Deoxyribonuclease II
+3.1.22.2	Aspergillus deoxyribonuclease K(1)
+3.1.22.3	Transferred entry: 3.1.21.7
+3.1.22.4	Crossover junction endodeoxyribonuclease
+3.1.22.5	Deoxyribonuclease X
+3.1.23.1	Transferred entry: 3.1.21.4
+3.1.23.2	Transferred entry: 3.1.21.4
+3.1.23.3	Transferred entry: 3.1.21.4
+3.1.23.4	Transferred entry: 3.1.21.4
+3.1.23.5	Transferred entry: 3.1.21.4
+3.1.23.6	Transferred entry: 3.1.21.4
+3.1.23.7	Transferred entry: 3.1.21.4
+3.1.23.8	Transferred entry: 3.1.21.4
+3.1.23.9	Transferred entry: 3.1.21.4
+3.1.23.10	Transferred entry: 3.1.21.4
+3.1.23.11	Transferred entry: 3.1.21.4
+3.1.23.12	Transferred entry: 3.1.21.4
+3.1.23.13	Transferred entry: 3.1.21.4
+3.1.23.14	Transferred entry: 3.1.21.4
+3.1.23.15	Transferred entry: 3.1.21.4
+3.1.23.16	Transferred entry: 3.1.21.4
+3.1.23.17	Transferred entry: 3.1.21.4
+3.1.23.18	Transferred entry: 3.1.21.4
+3.1.23.19	Transferred entry: 3.1.21.4
+3.1.23.20	Transferred entry: 3.1.21.4
+3.1.23.21	Transferred entry: 3.1.21.4
+3.1.23.22	Transferred entry: 3.1.21.4
+3.1.23.23	Transferred entry: 3.1.21.4
+3.1.23.24	Transferred entry: 3.1.21.4
+3.1.23.25	Transferred entry: 3.1.21.4
+3.1.23.26	Transferred entry: 3.1.21.4
+3.1.23.27	Transferred entry: 3.1.21.4
+3.1.23.28	Transferred entry: 3.1.21.4
+3.1.23.29	Transferred entry: 3.1.21.4
+3.1.23.30	Transferred entry: 3.1.21.4
+3.1.23.31	Transferred entry: 3.1.21.4
+3.1.23.32	Transferred entry: 3.1.21.4
+3.1.23.33	Transferred entry: 3.1.21.4
+3.1.23.34	Transferred entry: 3.1.21.4
+3.1.23.35	Transferred entry: 3.1.21.4
+3.1.23.36	Transferred entry: 3.1.21.4
+3.1.23.37	Transferred entry: 3.1.21.4
+3.1.23.38	Transferred entry: 3.1.21.4
+3.1.23.39	Transferred entry: 3.1.21.4
+3.1.23.40	Transferred entry: 3.1.21.4
+3.1.23.41	Transferred entry: 3.1.21.4
+3.1.23.42	Transferred entry: 3.1.21.4
+3.1.23.43	Transferred entry: 3.1.21.4
+3.1.23.44	Transferred entry: 3.1.21.4
+3.1.23.45	Transferred entry: 3.1.21.4
+3.1.23.46	Transferred entry: 3.1.21.4
+3.1.23.47	Transferred entry: 3.1.21.4
+3.1.23.48	Transferred entry: 3.1.21.4
+3.1.23.49	Transferred entry: 3.1.21.4
+3.1.23.50	Transferred entry: 3.1.21.4
+3.1.23.51	Transferred entry: 3.1.21.4
+3.1.23.52	Transferred entry: 3.1.21.4
+3.1.23.53	Transferred entry: 3.1.21.4
+3.1.23.54	Transferred entry: 3.1.21.4
+3.1.23.55	Transferred entry: 3.1.21.4
+3.1.23.56	Transferred entry: 3.1.21.4
+3.1.23.57	Transferred entry: 3.1.21.4
+3.1.23.58	Transferred entry: 3.1.21.4
+3.1.23.59	Transferred entry: 3.1.21.4
+3.1.24.1	Transferred entry: 3.1.21.3
+3.1.24.2	Transferred entry: 3.1.21.3
+3.1.24.3	Transferred entry: 3.1.21.5
+3.1.24.4	Transferred entry: 3.1.21.5
+3.1.25.1	Deoxyribonuclease (pyrimidine dimer)
+3.1.25.2	Transferred entry: 4.2.99.18
+3.1.26.1	Physarum polycephalum ribonuclease
+3.1.26.2	Ribonuclease alpha
+3.1.26.3	Ribonuclease III
+3.1.26.4	Ribonuclease H
+3.1.26.5	Ribonuclease P
+3.1.26.6	Ribonuclease IV
+3.1.26.7	Ribonuclease P4
+3.1.26.8	Ribonuclease M5
+3.1.26.9	Ribonuclease (poly-(U)-specific)
+3.1.26.10	Ribonuclease IX
+3.1.26.11	Ribonuclease Z
+3.1.26.12	Ribonuclease E
+3.1.26.13	Retroviral ribonuclease H
+3.1.27.1	Ribonuclease T(2)
+3.1.27.2	Bacillus subtilis ribonuclease
+3.1.27.3	Ribonuclease T(1)
+3.1.27.4	Ribonuclease U(2)
+3.1.27.5	Pancreatic ribonuclease
+3.1.27.6	Enterobacter ribonuclease
+3.1.27.7	Ribonuclease F
+3.1.27.8	Ribonuclease V
+3.1.27.9	Transferred entry: 4.6.1.16
+3.1.27.10	rRNA endonuclease
+3.1.30.1	Aspergillus nuclease S(1)
+3.1.30.2	Serratia marcescens nuclease
+3.1.31.1	Micrococcal nuclease
+3.2.1.1	Alpha-amylase
+3.2.1.2	Beta-amylase
+3.2.1.3	Glucan 1,4-alpha-glucosidase
+3.2.1.4	Cellulase
+3.2.1.5	Deleted entry
+3.2.1.6	Endo-1,3(4)-beta-glucanase
+3.2.1.7	Inulinase
+3.2.1.8	Endo-1,4-beta-xylanase
+3.2.1.9	Deleted entry
+3.2.1.10	Oligo-1,6-glucosidase
+3.2.1.11	Dextranase
+3.2.1.12	Transferred entry: 3.2.1.54
+3.2.1.13	Transferred entry: 3.2.1.54
+3.2.1.14	Chitinase
+3.2.1.15	Polygalacturonase
+3.2.1.16	Deleted entry
+3.2.1.17	Lysozyme
+3.2.1.18	Exo-alpha-sialidase
+3.2.1.19	Deleted entry
+3.2.1.20	Alpha-glucosidase
+3.2.1.21	Beta-glucosidase
+3.2.1.22	Alpha-galactosidase
+3.2.1.23	Beta-galactosidase
+3.2.1.24	Alpha-mannosidase
+3.2.1.25	Beta-mannosidase
+3.2.1.26	Beta-fructofuranosidase
+3.2.1.27	Deleted entry
+3.2.1.28	Alpha,alpha-trehalase
+3.2.1.29	Transferred entry: 3.2.1.52
+3.2.1.30	Transferred entry: 3.2.1.52
+3.2.1.31	Beta-glucuronidase
+3.2.1.32	Endo-1,3-beta-xylanase
+3.2.1.33	Amylo-alpha-1,6-glucosidase
+3.2.1.34	Transferred entry: 3.2.1.35
+3.2.1.35	Hyaluronoglucosaminidase
+3.2.1.36	Hyaluronoglucuronidase
+3.2.1.37	Xylan 1,4-beta-xylosidase
+3.2.1.38	Beta-D-fucosidase
+3.2.1.39	Glucan endo-1,3-beta-D-glucosidase
+3.2.1.40	Alpha-L-rhamnosidase
+3.2.1.41	Pullulanase
+3.2.1.42	GDP-glucosidase
+3.2.1.43	Beta-L-rhamnosidase
+3.2.1.44	Fucoidanase
+3.2.1.45	Glucosylceramidase
+3.2.1.46	Galactosylceramidase
+3.2.1.47	Galactosylgalactosylglucosylceramidase
+3.2.1.48	Sucrose alpha-glucosidase
+3.2.1.49	Alpha-N-acetylgalactosaminidase
+3.2.1.50	Alpha-N-acetylglucosaminidase
+3.2.1.51	Alpha-L-fucosidase
+3.2.1.52	Beta-N-acetylhexosaminidase
+3.2.1.53	Beta-N-acetylgalactosaminidase
+3.2.1.54	Cyclomaltodextrinase
+3.2.1.55	Non-reducing end alpha-L-arabinofuranosidase
+3.2.1.56	Glucuronosyl-disulfoglucosamine glucuronidase
+3.2.1.57	Isopullulanase
+3.2.1.58	Glucan 1,3-beta-glucosidase
+3.2.1.59	Glucan endo-1,3-alpha-glucosidase
+3.2.1.60	Glucan 1,4-alpha-maltotetraohydrolase
+3.2.1.61	Mycodextranase
+3.2.1.62	Glycosylceramidase
+3.2.1.63	1,2-alpha-L-fucosidase
+3.2.1.64	2,6-beta-fructan 6-levanbiohydrolase
+3.2.1.65	Levanase
+3.2.1.66	Quercitrinase
+3.2.1.67	Galacturan 1,4-alpha-galacturonidase
+3.2.1.68	Isoamylase
+3.2.1.69	Transferred entry: 3.2.1.41
+3.2.1.70	Glucan 1,6-alpha-glucosidase
+3.2.1.71	Glucan endo-1,2-beta-glucosidase
+3.2.1.72	Xylan 1,3-beta-xylosidase
+3.2.1.73	Licheninase
+3.2.1.74	Glucan 1,4-beta-glucosidase
+3.2.1.75	Glucan endo-1,6-beta-glucosidase
+3.2.1.76	L-iduronidase
+3.2.1.77	Mannan 1,2-(1,3)-alpha-mannosidase
+3.2.1.78	Mannan endo-1,4-beta-mannosidase
+3.2.1.79	Transferred entry: 3.2.1.55
+3.2.1.80	Fructan beta-fructosidase
+3.2.1.81	Beta-agarase
+3.2.1.82	Exo-poly-alpha-galacturonosidase
+3.2.1.83	Kappa-carrageenase
+3.2.1.84	Glucan 1,3-alpha-glucosidase
+3.2.1.85	6-phospho-beta-galactosidase
+3.2.1.86	6-phospho-beta-glucosidase
+3.2.1.87	Capsular-polysaccharide endo-1,3-alpha-galactosidase
+3.2.1.88	Non-reducing end beta-L-arabinopyranosidase
+3.2.1.89	Arabinogalactan endo-beta-1,4-galactanase
+3.2.1.90	Deleted entry
+3.2.1.91	Cellulose 1,4-beta-cellobiosidase (non-reducing end)
+3.2.1.92	Peptidoglycan beta-N-acetylmuramidase
+3.2.1.93	Alpha,alpha-phosphotrehalase
+3.2.1.94	Glucan 1,6-alpha-isomaltosidase
+3.2.1.95	Dextran 1,6-alpha-isomaltotriosidase
+3.2.1.96	Mannosyl-glycoprotein endo-beta-N-acetylglucosaminidase
+3.2.1.97	Endo-alpha-N-acetylgalactosaminidase
+3.2.1.98	Glucan 1,4-alpha-maltohexaosidase
+3.2.1.99	Arabinan endo-1,5-alpha-L-arabinosidase
+3.2.1.100	Mannan 1,4-mannobiosidase
+3.2.1.101	Mannan endo-1,6-alpha-mannosidase
+3.2.1.102	Blood-group-substance endo-1,4-beta-galactosidase
+3.2.1.103	Keratan-sulfate endo-1,4-beta-galactosidase
+3.2.1.104	Steryl-beta-glucosidase
+3.2.1.105	3-alpha-(S)-strictosidine beta-glucosidase
+3.2.1.106	Mannosyl-oligosaccharide glucosidase
+3.2.1.107	Protein-glucosylgalactosylhydroxylysine glucosidase
+3.2.1.108	Lactase
+3.2.1.109	Endogalactosaminidase
+3.2.1.110	Transferred entry: 3.2.1.97
+3.2.1.111	1,3-alpha-L-fucosidase
+3.2.1.112	2-deoxyglucosidase
+3.2.1.113	Mannosyl-oligosaccharide 1,2-alpha-mannosidase
+3.2.1.114	Mannosyl-oligosaccharide 1,3-1,6-alpha-mannosidase
+3.2.1.115	Branched-dextran exo-1,2-alpha-glucosidase
+3.2.1.116	Glucan 1,4-alpha-maltotriohydrolase
+3.2.1.117	Amygdalin beta-glucosidase
+3.2.1.118	Prunasin beta-glucosidase
+3.2.1.119	Vicianin beta-glucosidase
+3.2.1.120	Oligoxyloglucan beta-glycosidase
+3.2.1.121	Polymannuronate hydrolase
+3.2.1.122	Maltose-6'-phosphate glucosidase
+3.2.1.123	Endoglycosylceramidase
+3.2.1.124	3-deoxy-2-octulosonidase
+3.2.1.125	Raucaffricine beta-glucosidase
+3.2.1.126	Coniferin beta-glucosidase
+3.2.1.127	1,6-alpha-L-fucosidase
+3.2.1.128	Glycyrrhizinate beta-glucuronidase
+3.2.1.129	Endo-alpha-sialidase
+3.2.1.130	Glycoprotein endo-alpha-1,2-mannosidase
+3.2.1.131	Xylan alpha-1,2-glucuronosidase
+3.2.1.132	Chitosanase
+3.2.1.133	Glucan 1,4-alpha-maltohydrolase
+3.2.1.134	Difructose-anhydride synthase
+3.2.1.135	Neopullulanase
+3.2.1.136	Glucuronoarabinoxylan endo-1,4-beta-xylanase
+3.2.1.137	Mannan exo-1,2-1,6-alpha-mannosidase
+3.2.1.138	Transferred entry: 4.2.2.15
+3.2.1.139	Alpha-glucuronidase
+3.2.1.140	Lacto-N-biosidase
+3.2.1.141	4-alpha-D-((1->4)-alpha-D-glucano)trehalose trehalohydrolase
+3.2.1.142	Limit dextrinase
+3.2.1.143	Poly(ADP-ribose) glycohydrolase
+3.2.1.144	3-deoxyoctulosonase
+3.2.1.145	Galactan 1,3-beta-galactosidase
+3.2.1.146	Beta-galactofuranosidase
+3.2.1.147	Thioglucosidase
+3.2.1.148	Transferred entry: 4.4.1.21
+3.2.1.149	Beta-primeverosidase
+3.2.1.150	Oligoxyloglucan reducing-end-specific cellobiohydrolase
+3.2.1.151	Xyloglucan-specific endo-beta-1,4-glucanase
+3.2.1.152	Mannosylglycoprotein endo-beta-mannosidase
+3.2.1.153	Fructan beta-(2,1)-fructosidase
+3.2.1.154	Fructan beta-(2,6)-fructosidase
+3.2.1.155	Xyloglucan-specific exo-beta-1,4-glucanase
+3.2.1.156	Oligosaccharide reducing-end xylanase
+3.2.1.157	Iota-carrageenase
+3.2.1.158	Alpha-agarase
+3.2.1.159	Alpha-neoagaro-oligosaccharide hydrolase
+3.2.1.160	Transferred entry: 3.2.1.155
+3.2.1.161	Beta-apiosyl-beta-glucosidase
+3.2.1.162	Lambda-carrageenase
+3.2.1.163	1,6-alpha-D-mannosidase
+3.2.1.164	Galactan endo-1,6-beta-galactosidase
+3.2.1.165	Exo-1,4-beta-D-glucosaminidase
+3.2.1.166	Heparanase
+3.2.1.167	Baicalin-beta-D-glucuronidase
+3.2.1.168	Hesperidin 6-O-alpha-L-rhamnosyl-beta-D-glucosidase
+3.2.1.169	Protein O-GlcNAcase
+3.2.1.170	Mannosylglycerate hydrolase
+3.2.1.171	Rhamnogalacturonan hydrolase
+3.2.1.172	Unsaturated rhamnogalacturonyl hydrolase
+3.2.1.173	Rhamnogalacturonan galacturonohydrolase
+3.2.1.174	Rhamnogalacturonan rhamnohydrolase
+3.2.1.175	Beta-D-glucopyranosyl abscisate beta-glucosidase
+3.2.1.176	Cellulose 1,4-beta-cellobiosidase (reducing end)
+3.2.1.177	Alpha-D-xyloside xylohydrolase
+3.2.1.178	Beta-porphyranase
+3.2.1.179	Gellan tetrasaccharide unsaturated glucuronyl hydrolase
+3.2.1.180	Unsaturated chondroitin disaccharide hydrolase
+3.2.1.181	Galactan endo-beta-1,3-galactanase
+3.2.1.182	beta-D-glucosidase
+3.2.1.183	UDP-N-acetylglucosamine 2-epimerase (hydrolyzing)
+3.2.1.184	UDP-N,N'-diacetylbacillosamine 2-epimerase (hydrolyzing)
+3.2.1.185	Non-reducing end beta-L-arabinofuranosidase
+3.2.1.186	Protodioscin 26-O-beta-D-glucosidase
+3.2.1.187	(Ara-f)(3)-Hyp beta-L-arabinobiosidase
+3.2.1.188	Avenacosidase
+3.2.1.189	Dioscin glycosidase (diosgenin-forming)
+3.2.1.190	Dioscin glycosidase (3-O-beta-D-Glc-diosgenin-forming)
+3.2.1.191	Ginsenosidase type III
+3.2.1.192	Ginsenoside Rb1 beta-glucosidase
+3.2.1.193	Ginsenosidase type I
+3.2.1.194	Ginsenosidase type IV
+3.2.1.195	20-O-multi-glycoside ginsenosidase
+3.2.2.1	Purine nucleosidase
+3.2.2.2	Inosine nucleosidase
+3.2.2.3	Uridine nucleosidase
+3.2.2.4	AMP nucleosidase
+3.2.2.5	NAD(+) glycohydrolase
+3.2.2.6	ADP-ribosyl cyclase/cyclic ADP-ribose hydrolase
+3.2.2.7	Adenosine nucleosidase
+3.2.2.8	Ribosylpyrimidine nucleosidase
+3.2.2.9	Adenosylhomocysteine nucleosidase
+3.2.2.10	Pyrimidine-5'-nucleotide nucleosidase
+3.2.2.11	Beta-aspartyl-N-acetylglucosaminidase
+3.2.2.12	Inosinate nucleosidase
+3.2.2.13	1-methyladenosine nucleosidase
+3.2.2.14	NMN nucleosidase
+3.2.2.15	DNA-deoxyinosine glycosylase
+3.2.2.16	Methylthioadenosine nucleosidase
+3.2.2.17	Deoxyribodipyrimidine endonucleosidase
+3.2.2.18	Transferred entry: 3.5.1.52
+3.2.2.19	[Protein ADP-ribosylarginine] hydrolase
+3.2.2.20	DNA-3-methyladenine glycosylase I
+3.2.2.21	DNA-3-methyladenine glycosylase II
+3.2.2.22	rRNA N-glycosylase
+3.2.2.23	DNA-formamidopyrimidine glycosylase
+3.2.2.24	ADP-ribosyl-[dinitrogen reductase] hydrolase
+3.2.2.25	N-methyl nucleosidase
+3.2.2.26	Futalosine hydrolase
+3.2.2.27	Uracil-DNA glycosylase
+3.2.2.28	Double-stranded uracil-DNA glycosylase
+3.2.2.29	Thymine-DNA glycosylase
+3.2.2.30	Aminodeoxyfutalosine nucleosidase
+3.2.3.1	Transferred entry: 3.2.1.147
+3.3.1.1	Adenosylhomocysteinase
+3.3.1.2	Adenosylmethionine hydrolase
+3.3.1.3	Transferred entry: 4.4.1.21
+3.3.2.1	Isochorismatase
+3.3.2.2	Alkenylglycerophosphocholine hydrolase
+3.3.2.3	Transferred entry: 3.3.2.9 and 3.3.2.10
+3.3.2.4	Trans-epoxysuccinate hydrolase
+3.3.2.5	Alkenylglycerophosphoethanolamine hydrolase
+3.3.2.6	Leukotriene-A(4) hydrolase
+3.3.2.7	Hepoxilin-epoxide hydrolase
+3.3.2.8	Limonene-1,2-epoxide hydrolase
+3.3.2.9	Microsomal epoxide hydrolase
+3.3.2.10	Soluble epoxide hydrolase
+3.3.2.11	Cholesterol-5,6-oxide hydrolase
+3.3.2.12	Oxepin-CoA hydrolase
+3.3.2.13	Chorismatase
+3.3.2.14	2,4-dinitroanisole O-demethylase
+3.4.1.1	Transferred entry: 3.4.11.1
+3.4.1.2	Transferred entry: 3.4.11.2
+3.4.1.3	Transferred entry: 3.4.11.4
+3.4.1.4	Transferred entry: 3.4.11.5
+3.4.2.1	Transferred entry: 3.4.17.1
+3.4.2.2	Transferred entry: 3.4.17.2
+3.4.2.3	Transferred entry: 3.4.17.4
+3.4.3.1	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.3.2	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.3.3	Transferred entry: 3.4.13.18 and 3.4.13.20
+3.4.3.4	Transferred entry: 3.4.13.5
+3.4.3.5	Transferred entry: 3.4.11.2
+3.4.3.6	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.3.7	Transferred entry: 3.4.13.9
+3.4.4.1	Transferred entry: 3.4.23.1
+3.4.4.2	Transferred entry: 3.4.23.2
+3.4.4.3	Transferred entry: 3.4.23.4
+3.4.4.4	Transferred entry: 3.4.21.4
+3.4.4.5	Transferred entry: 3.4.21.1
+3.4.4.6	Transferred entry: 3.4.21.1
+3.4.4.7	Transferred entry: 3.4.21.36 and 3.4.21.37
+3.4.4.8	Transferred entry: 3.4.21.9
+3.4.4.9	Transferred entry: 3.4.14.1
+3.4.4.10	Transferred entry: 3.4.22.2
+3.4.4.11	Transferred entry: 3.4.22.6
+3.4.4.12	Transferred entry: 3.4.22.3
+3.4.4.13	Transferred entry: 3.4.21.5
+3.4.4.14	Transferred entry: 3.4.21.7
+3.4.4.15	Transferred entry: 3.4.23.15
+3.4.4.16	and 3.4.21.67
+3.4.4.17	3.4.23.30
+3.4.4.18	Transferred entry: 3.4.22.10
+3.4.4.19	Transferred entry: 3.4.24.3
+3.4.4.20	Transferred entry: 3.4.22.8
+3.4.4.21	Transferred entry: 3.4.21.34
+3.4.4.22	Transferred entry: 3.4.23.3
+3.4.4.23	Transferred entry: 3.4.23.5
+3.4.4.24	Transferred entry: 3.4.22.32 and 3.4.22.33
+3.4.4.25	Deleted entry
+3.4.11.1	Leucyl aminopeptidase
+3.4.11.2	Membrane alanyl aminopeptidase
+3.4.11.3	Cystinyl aminopeptidase
+3.4.11.4	Tripeptide aminopeptidase
+3.4.11.5	Prolyl aminopeptidase
+3.4.11.6	Aminopeptidase B
+3.4.11.7	Glutamyl aminopeptidase
+3.4.11.8	Transferred entry: 3.4.19.3
+3.4.11.9	Xaa-Pro aminopeptidase
+3.4.11.10	Bacterial leucyl aminopeptidase
+3.4.11.11	Deleted entry
+3.4.11.12	Deleted entry
+3.4.11.13	Clostridial aminopeptidase
+3.4.11.14	Cytosol alanyl aminopeptidase
+3.4.11.15	Aminopeptidase Y
+3.4.11.16	Xaa-Trp aminopeptidase
+3.4.11.17	Tryptophanyl aminopeptidase
+3.4.11.18	Methionyl aminopeptidase
+3.4.11.19	D-stereospecific aminopeptidase
+3.4.11.20	Aminopeptidase Ey
+3.4.11.21	Aspartyl aminopeptidase
+3.4.11.22	Aminopeptidase I
+3.4.11.23	PepB aminopeptidase
+3.4.11.24	Aminopeptidase S
+3.4.11.25	Beta-peptidyl aminopeptidase
+3.4.11.26	Intermediate cleaving peptidase 55
+3.4.12.1	Transferred entry: 3.4.16.5 and 3.4.16.6
+3.4.12.2	Transferred entry: 3.4.17.1
+3.4.12.3	Transferred entry: 3.4.17.2
+3.4.12.4	Transferred entry: 3.4.16.2
+3.4.12.5	Transferred entry: 3.5.1.28
+3.4.12.6	Transferred entry: 3.4.17.8
+3.4.12.7	Transferred entry: 3.4.17.3
+3.4.12.8	Transferred entry: 3.4.17.4
+3.4.12.9	Deleted entry
+3.4.12.10	Transferred entry: 3.4.19.9
+3.4.12.11	Transferred entry: 3.4.17.6
+3.4.12.12	Transferred entry: 3.4.16.5 and 3.4.16.6
+3.4.12.13	Deleted entry
+3.4.13.1	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.13.2	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.13.3	Transferred entry: 3.4.13.18 and 3.4.13.20
+3.4.13.4	Xaa-Arg dipeptidase
+3.4.13.5	Xaa-methyl-His dipeptidase
+3.4.13.6	Transferred entry: 3.4.11.2
+3.4.13.7	Glu-Glu dipeptidase
+3.4.13.8	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.13.9	Xaa-Pro dipeptidase
+3.4.13.10	Transferred entry: 3.4.19.5
+3.4.13.11	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.13.12	Met-Xaa dipeptidase
+3.4.13.13	Transferred entry: 3.4.13.18 and 3.4.13.20
+3.4.13.14	Deleted entry
+3.4.13.15	Transferred entry: 3.4.13.18 and 3.4.13.19
+3.4.13.16	Deleted entry
+3.4.13.17	Non-stereospecific dipeptidase
+3.4.13.18	Cytosol nonspecific dipeptidase
+3.4.13.19	Membrane dipeptidase
+3.4.13.20	Beta-Ala-His dipeptidase
+3.4.13.21	Dipeptidase E
+3.4.13.22	D-Ala-D-Ala dipeptidase
+3.4.14.1	Dipeptidyl-peptidase I
+3.4.14.2	Dipeptidyl-peptidase II
+3.4.14.3	Transferred entry: 3.4.19.1
+3.4.14.4	Dipeptidyl-peptidase III
+3.4.14.5	Dipeptidyl-peptidase IV
+3.4.14.6	Dipeptidyl-dipeptidase
+3.4.14.7	Deleted entry
+3.4.14.8	Transferred entry: 3.4.14.9 and 3.4.14.10
+3.4.14.9	Tripeptidyl-peptidase I
+3.4.14.10	Tripeptidyl-peptidase II
+3.4.14.11	Xaa-Pro dipeptidyl-peptidase
+3.4.14.12	Xaa-Xaa-Pro tripeptidyl-peptidase
+3.4.14.13	Gamma-D-glutamyl-L-lysine dipeptidyl-peptidase
+3.4.15.1	Peptidyl-dipeptidase A
+3.4.15.2	Transferred entry: 3.4.19.2
+3.4.15.3	Transferred entry: 3.4.15.5
+3.4.15.4	Peptidyl-dipeptidase B
+3.4.15.5	Peptidyl-dipeptidase Dcp
+3.4.15.6	Cyanophycinase
+3.4.16.1	Transferred entry: 3.4.16.5 and 3.4.16.6
+3.4.16.2	Lysosomal Pro-Xaa carboxypeptidase
+3.4.16.3	Transferred entry: 3.4.16.5 and 3.4.16.6
+3.4.16.4	Serine-type D-Ala-D-Ala carboxypeptidase
+3.4.16.5	Carboxypeptidase C
+3.4.16.6	Carboxypeptidase D
+3.4.17.1	Carboxypeptidase A
+3.4.17.2	Carboxypeptidase B
+3.4.17.3	Lysine carboxypeptidase
+3.4.17.4	Gly-Xaa carboxypeptidase
+3.4.17.5	Deleted entry
+3.4.17.6	Alanine carboxypeptidase
+3.4.17.7	Transferred entry: 3.5.1.28
+3.4.17.8	Muramoylpentapeptide carboxypeptidase
+3.4.17.9	Transferred entry: 3.4.17.4
+3.4.17.10	Carboxypeptidase E
+3.4.17.11	Glutamate carboxypeptidase
+3.4.17.12	Carboxypeptidase M
+3.4.17.13	Muramoyltetrapeptide carboxypeptidase
+3.4.17.14	Zinc D-Ala-D-Ala carboxypeptidase
+3.4.17.15	Carboxypeptidase A2
+3.4.17.16	Membrane Pro-Xaa carboxypeptidase
+3.4.17.17	Tubulinyl-Tyr carboxypeptidase
+3.4.17.18	Carboxypeptidase T
+3.4.17.19	Carboxypeptidase Taq
+3.4.17.20	Carboxypeptidase U
+3.4.17.21	Glutamate carboxypeptidase II
+3.4.17.22	Metallocarboxypeptidase D
+3.4.17.23	Angiotensin-converting enzyme 2
+3.4.18.1	Cathepsin X
+3.4.19.1	Acylaminoacyl-peptidase
+3.4.19.2	Peptidyl-glycinamidase
+3.4.19.3	Pyroglutamyl-peptidase I
+3.4.19.4	Deleted entry
+3.4.19.5	Beta-aspartyl-peptidase
+3.4.19.6	Pyroglutamyl-peptidase II
+3.4.19.7	N-formylmethionyl-peptidase
+3.4.19.8	Transferred entry: 3.4.17.21
+3.4.19.9	Gamma-glutamyl hydrolase
+3.4.19.10	Transferred entry: 3.5.1.28
+3.4.19.11	Gamma-D-glutamyl-meso-diaminopimelate peptidase
+3.4.19.12	Ubiquitinyl hydrolase 1
+3.4.19.13	Glutathione hydrolase
+3.4.19.14	Leukotriene-C(4) hydrolase
+3.4.21.1	Chymotrypsin
+3.4.21.2	Chymotrypsin C
+3.4.21.3	Metridin
+3.4.21.4	Trypsin
+3.4.21.5	Thrombin
+3.4.21.6	Coagulation factor Xa
+3.4.21.7	Plasmin
+3.4.21.8	Transferred entry: 3.4.21.34 and 3.4.21.35
+3.4.21.9	Enteropeptidase
+3.4.21.10	Acrosin
+3.4.21.11	Transferred entry: 3.4.21.36 and 3.4.21.37
+3.4.21.12	Alpha-lytic endopeptidase
+3.4.21.13	Transferred entry: 3.4.16.5 and 3.4.16.6
+3.4.21.14	3.4.21.67
+3.4.21.15	Transferred entry: 3.4.21.63
+3.4.21.16	Deleted entry
+3.4.21.17	Deleted entry
+3.4.21.18	Deleted entry
+3.4.21.19	Glutamyl endopeptidase
+3.4.21.20	Cathepsin G
+3.4.21.21	Coagulation factor VIIa
+3.4.21.22	Coagulation factor IXa
+3.4.21.23	Deleted entry
+3.4.21.24	Deleted entry
+3.4.21.25	Cucumisin
+3.4.21.26	Prolyl oligopeptidase
+3.4.21.27	Coagulation factor XIa
+3.4.21.28	Transferred entry: 3.4.21.74
+3.4.21.29	Transferred entry: 3.4.21.74
+3.4.21.30	Transferred entry: 3.4.21.74
+3.4.21.31	Transferred entry: 3.4.21.68 and 3.4.21.73
+3.4.21.32	Brachyurin
+3.4.21.33	Deleted entry
+3.4.21.34	Plasma kallikrein
+3.4.21.35	Tissue kallikrein
+3.4.21.36	Pancreatic elastase
+3.4.21.37	Leukocyte elastase
+3.4.21.38	Coagulation factor XIIa
+3.4.21.39	Chymase
+3.4.21.40	Deleted entry
+3.4.21.41	Complement subcomponent C1r
+3.4.21.42	Complement subcomponent C1s
+3.4.21.43	Classical-complement-pathway C3/C5 convertase
+3.4.21.44	Transferred entry: 3.4.21.43
+3.4.21.45	Complement factor I
+3.4.21.46	Complement factor D
+3.4.21.47	Alternative-complement-pathway C3/C5 convertase
+3.4.21.48	Cerevisin
+3.4.21.49	Hypodermin C
+3.4.21.50	Lysyl endopeptidase
+3.4.21.51	Deleted entry
+3.4.21.52	Deleted entry
+3.4.21.53	Endopeptidase La
+3.4.21.54	Gamma-renin
+3.4.21.55	Venombin AB
+3.4.21.56	Deleted entry
+3.4.21.57	Leucyl endopeptidase
+3.4.21.58	Deleted entry
+3.4.21.59	Tryptase
+3.4.21.60	Scutelarin
+3.4.21.61	Kexin
+3.4.21.62	Subtilisin
+3.4.21.63	Oryzin
+3.4.21.64	Peptidase K
+3.4.21.65	Thermomycolin
+3.4.21.66	Thermitase
+3.4.21.67	Endopeptidase So
+3.4.21.68	T-plasminogen activator
+3.4.21.69	Protein C (activated)
+3.4.21.70	Pancreatic endopeptidase E
+3.4.21.71	Pancreatic elastase II
+3.4.21.72	IgA-specific serine endopeptidase
+3.4.21.73	U-plasminogen activator
+3.4.21.74	Venombin A
+3.4.21.75	Furin
+3.4.21.76	Myeloblastin
+3.4.21.77	Semenogelase
+3.4.21.78	Granzyme A
+3.4.21.79	Granzyme B
+3.4.21.80	Streptogrisin A
+3.4.21.81	Streptogrisin B
+3.4.21.82	Glutamyl endopeptidase II
+3.4.21.83	Oligopeptidase B
+3.4.21.84	Limulus clotting factor C
+3.4.21.85	Limulus clotting factor B
+3.4.21.86	Limulus clotting enzyme
+3.4.21.87	Transferred entry: 3.4.23.49
+3.4.21.88	Repressor LexA
+3.4.21.89	Signal peptidase I
+3.4.21.90	Togavirin
+3.4.21.91	Flavivirin
+3.4.21.92	Endopeptidase Clp
+3.4.21.93	Proprotein convertase 1
+3.4.21.94	Proprotein convertase 2
+3.4.21.95	Snake venom factor V activator
+3.4.21.96	Lactocepin
+3.4.21.97	Assemblin
+3.4.21.98	Hepacivirin
+3.4.21.99	Spermosin
+3.4.21.100	Sedolisin
+3.4.21.101	Xanthomonalisin
+3.4.21.102	C-terminal processing peptidase
+3.4.21.103	Physarolisin
+3.4.21.104	Mannan-binding lectin-associated serine protease-2
+3.4.21.105	Rhomboid protease
+3.4.21.106	Hepsin
+3.4.21.107	Peptidase Do
+3.4.21.108	HtrA2 peptidase
+3.4.21.109	Matriptase
+3.4.21.110	C5a peptidase
+3.4.21.111	Aqualysin 1
+3.4.21.112	Site-1 protease
+3.4.21.113	Pestivirus NS3 polyprotein peptidase
+3.4.21.114	Equine arterivirus serine peptidase
+3.4.21.115	Infectious pancreatic necrosis birnavirus Vp4 peptidase
+3.4.21.116	SpoIVB peptidase
+3.4.21.117	Stratum corneum chymotryptic enzyme
+3.4.21.118	Kallikrein 8
+3.4.21.119	Kallikrein 13
+3.4.21.120	Oviductin
+3.4.21.121	Lys-Lys/Arg-Xaa endopeptidase
+3.4.22.1	Cathepsin B
+3.4.22.2	Papain
+3.4.22.3	Ficain
+3.4.22.4	Transferred entry: 3.4.22.32 and 3.4.22.33
+3.4.22.5	Transferred entry: 3.4.22.33
+3.4.22.6	Chymopapain
+3.4.22.7	Asclepain
+3.4.22.8	Clostripain
+3.4.22.9	Transferred entry: 3.4.21.48
+3.4.22.10	Streptopain
+3.4.22.11	Transferred entry: 3.4.24.56
+3.4.22.12	Transferred entry: 3.4.19.9
+3.4.22.13	Deleted entry
+3.4.22.14	Actinidain
+3.4.22.15	Cathepsin L
+3.4.22.16	Cathepsin H
+3.4.22.17	Transferred entry: 3.4.22.52 and 3.4.22.53
+3.4.22.18	Transferred entry: 3.4.21.26
+3.4.22.19	Transferred entry: 3.4.24.15
+3.4.22.20	Deleted entry
+3.4.22.21	Transferred entry: 3.4.25.1
+3.4.22.22	Transferred entry: 3.4.24.37
+3.4.22.23	Transferred entry: 3.4.21.61
+3.4.22.24	Cathepsin T
+3.4.22.25	Glycyl endopeptidase
+3.4.22.26	Cancer procoagulant
+3.4.22.27	Cathepsin S
+3.4.22.28	Picornain 3C
+3.4.22.29	Picornain 2A
+3.4.22.30	Caricain
+3.4.22.31	Ananain
+3.4.22.32	Stem bromelain
+3.4.22.33	Fruit bromelain
+3.4.22.34	Legumain
+3.4.22.35	Histolysain
+3.4.22.36	Caspase-1
+3.4.22.37	Gingipain R
+3.4.22.38	Cathepsin K
+3.4.22.39	Adenain
+3.4.22.40	Bleomycin hydrolase
+3.4.22.41	Cathepsin F
+3.4.22.42	Cathepsin O
+3.4.22.43	Cathepsin V
+3.4.22.44	Nuclear-inclusion-a endopeptidase
+3.4.22.45	Helper-component proteinase
+3.4.22.46	L-peptidase
+3.4.22.47	Gingipain K
+3.4.22.48	Staphopain
+3.4.22.49	Separase
+3.4.22.50	V-cath endopeptidase
+3.4.22.51	Cruzipain
+3.4.22.52	Calpain-1
+3.4.22.53	Calpain-2
+3.4.22.54	Calpain-3
+3.4.22.55	Caspase-2
+3.4.22.56	Caspase-3
+3.4.22.57	Caspase-4
+3.4.22.58	Caspase-5
+3.4.22.59	Caspase-6
+3.4.22.60	Caspase-7
+3.4.22.61	Caspase-8
+3.4.22.62	Caspase-9
+3.4.22.63	Caspase-10
+3.4.22.64	Caspase-11
+3.4.22.65	Peptidase 1 (mite)
+3.4.22.66	Calicivirin
+3.4.22.67	Zingipain
+3.4.22.68	Ulp1 peptidase
+3.4.22.69	SARS coronavirus main proteinase
+3.4.22.70	Sortase A
+3.4.22.71	Sortase B
+3.4.23.1	Pepsin A
+3.4.23.2	Pepsin B
+3.4.23.3	Gastricsin
+3.4.23.4	Chymosin
+3.4.23.5	Cathepsin D
+3.4.23.6	3.4.23.28 and 3.4.23.30
+3.4.23.7	Transferred entry: 3.4.23.20
+3.4.23.8	Transferred entry: 3.4.23.25
+3.4.23.9	Transferred entry: 3.4.23.21
+3.4.23.10	Transferred entry: 3.4.23.22
+3.4.23.11	Deleted entry
+3.4.23.12	Nepenthesin
+3.4.23.13	Deleted entry
+3.4.23.14	Deleted entry
+3.4.23.15	Renin
+3.4.23.16	HIV-1 retropepsin
+3.4.23.17	Pro-opiomelanocortin converting enzyme
+3.4.23.18	Aspergillopepsin I
+3.4.23.19	Aspergillopepsin II
+3.4.23.20	Penicillopepsin
+3.4.23.21	Rhizopuspepsin
+3.4.23.22	Endothiapepsin
+3.4.23.23	Mucorpepsin
+3.4.23.24	Candidapepsin
+3.4.23.25	Saccharopepsin
+3.4.23.26	Rhodotorulapepsin
+3.4.23.27	Transferred entry: 3.4.21.103
+3.4.23.28	Acrocylindropepsin
+3.4.23.29	Polyporopepsin
+3.4.23.30	Pycnoporopepsin
+3.4.23.31	Scytalidopepsin A
+3.4.23.32	Scytalidopepsin B
+3.4.23.33	Transferred entry: 3.4.21.101
+3.4.23.34	Cathepsin E
+3.4.23.35	Barrierpepsin
+3.4.23.36	Signal peptidase II
+3.4.23.37	Transferred entry: 3.4.21.100
+3.4.23.38	Plasmepsin I
+3.4.23.39	Plasmepsin II
+3.4.23.40	Phytepsin
+3.4.23.41	Yapsin 1
+3.4.23.42	Thermopsin
+3.4.23.43	Prepilin peptidase
+3.4.23.44	Nodavirus endopeptidase
+3.4.23.45	Memapsin 1
+3.4.23.46	Memapsin 2
+3.4.23.47	HIV-2 retropepsin
+3.4.23.48	Plasminogen activator Pla
+3.4.23.49	Omptin
+3.4.23.50	Human endogenous retrovirus K endopeptidase
+3.4.23.51	HycI peptidase
+3.4.23.52	Preflagellin peptidase
+3.4.24.1	Atrolysin A
+3.4.24.2	Deleted entry
+3.4.24.3	Microbial collagenase
+3.4.24.4	3.4.24.30, 3.4.24.31, 3.4.24.32, 3.4.24.39 and 3.4.24.40
+3.4.24.5	Transferred entry: 3.4.22.52, 3.4.22.53 and 3.4.25.1
+3.4.24.6	Leucolysin
+3.4.24.7	Interstitial collagenase
+3.4.24.8	Transferred entry: 3.4.24.3
+3.4.24.9	Deleted entry
+3.4.24.10	Deleted entry
+3.4.24.11	Neprilysin
+3.4.24.12	Envelysin
+3.4.24.13	IgA-specific metalloendopeptidase
+3.4.24.14	Procollagen N-endopeptidase
+3.4.24.15	Thimet oligopeptidase
+3.4.24.16	Neurolysin
+3.4.24.17	Stromelysin 1
+3.4.24.18	Meprin A
+3.4.24.19	Procollagen C-endopeptidase
+3.4.24.20	Peptidyl-Lys metalloendopeptidase
+3.4.24.21	Astacin
+3.4.24.22	Stromelysin 2
+3.4.24.23	Matrilysin
+3.4.24.24	Gelatinase A
+3.4.24.25	Vibriolysin
+3.4.24.26	Pseudolysin
+3.4.24.27	Thermolysin
+3.4.24.28	Bacillolysin
+3.4.24.29	Aureolysin
+3.4.24.30	Coccolysin
+3.4.24.31	Mycolysin
+3.4.24.32	Beta-lytic metalloendopeptidase
+3.4.24.33	Peptidyl-Asp metalloendopeptidase
+3.4.24.34	Neutrophil collagenase
+3.4.24.35	Gelatinase B
+3.4.24.36	Leishmanolysin
+3.4.24.37	Saccharolysin
+3.4.24.38	Gametolysin
+3.4.24.39	Deuterolysin
+3.4.24.40	Serralysin
+3.4.24.41	Atrolysin B
+3.4.24.42	Atrolysin C
+3.4.24.43	Atroxase
+3.4.24.44	Atrolysin E
+3.4.24.45	Atrolysin F
+3.4.24.46	Adamalysin
+3.4.24.47	Horrilysin
+3.4.24.48	Ruberlysin
+3.4.24.49	Bothropasin
+3.4.24.50	Bothrolysin
+3.4.24.51	Ophiolysin
+3.4.24.52	Trimerelysin I
+3.4.24.53	Trimerelysin II
+3.4.24.54	Mucrolysin
+3.4.24.55	Pitrilysin
+3.4.24.56	Insulysin
+3.4.24.57	O-sialoglycoprotein endopeptidase
+3.4.24.58	Russellysin
+3.4.24.59	Mitochondrial intermediate peptidase
+3.4.24.60	Dactylysin
+3.4.24.61	Nardilysin
+3.4.24.62	Magnolysin
+3.4.24.63	Meprin B
+3.4.24.64	Mitochondrial processing peptidase
+3.4.24.65	Macrophage elastase
+3.4.24.66	Choriolysin L
+3.4.24.67	Choriolysin H
+3.4.24.68	Tentoxilysin
+3.4.24.69	Bontoxilysin
+3.4.24.70	Oligopeptidase A
+3.4.24.71	Endothelin-converting enzyme 1
+3.4.24.72	Fibrolase
+3.4.24.73	Jararhagin
+3.4.24.74	Fragilysin
+3.4.24.75	Lysostaphin
+3.4.24.76	Flavastacin
+3.4.24.77	Snapalysin
+3.4.24.78	GPR endopeptidase
+3.4.24.79	Pappalysin-1
+3.4.24.80	Membrane-type matrix metalloproteinase-1
+3.4.24.81	ADAM10 endopeptidase
+3.4.24.82	ADAMTS-4 endopeptidase
+3.4.24.83	Anthrax lethal factor endopeptidase
+3.4.24.84	Ste24 endopeptidase
+3.4.24.85	S2P endopeptidase
+3.4.24.86	ADAM 17 endopeptidase
+3.4.24.87	ADAMTS13 endopeptidase
+3.4.24.88	Desampylase
+3.4.24.89	Pro-Pro endopeptidase
+3.4.25.1	Proteasome endopeptidase complex
+3.4.25.2	HslU--HslV peptidase
+3.4.99.1	Transferred entry: 3.4.23.28
+3.4.99.2	Deleted entry
+3.4.99.3	Deleted entry
+3.4.99.4	Transferred entry: 3.4.23.12
+3.4.99.5	Transferred entry: 3.4.24.3
+3.4.99.6	Transferred entry: 3.4.24.21
+3.4.99.7	Deleted entry
+3.4.99.8	Deleted entry
+3.4.99.9	Deleted entry
+3.4.99.10	Transferred entry: 3.4.24.56
+3.4.99.11	Deleted entry
+3.4.99.12	Deleted entry
+3.4.99.13	Transferred entry: 3.4.24.32
+3.4.99.14	Deleted entry
+3.4.99.15	Deleted entry
+3.4.99.16	Deleted entry
+3.4.99.17	Deleted entry
+3.4.99.18	Deleted entry
+3.4.99.19	Transferred entry: 3.4.23.15
+3.4.99.20	Deleted entry
+3.4.99.21	Deleted entry
+3.4.99.22	Transferred entry: 3.4.24.29
+3.4.99.23	Deleted entry
+3.4.99.24	Deleted entry
+3.4.99.25	Transferred entry: 3.4.23.21
+3.4.99.26	Transferred entry: 3.4.21.68 and 3.4.21.73
+3.4.99.27	Deleted entry
+3.4.99.28	Transferred entry: 3.4.21.60
+3.4.99.29	Deleted entry
+3.4.99.30	Transferred entry: 3.4.24.20
+3.4.99.31	Transferred entry: 3.4.24.15
+3.4.99.32	Transferred entry: 3.4.24.20
+3.4.99.33	Deleted entry
+3.4.99.34	Deleted entry
+3.4.99.35	Transferred entry: 3.4.23.36
+3.4.99.36	Transferred entry: 3.4.21.89
+3.4.99.37	Deleted entry
+3.4.99.38	Transferred entry: 3.4.23.17
+3.4.99.39	Deleted entry
+3.4.99.40	Deleted entry
+3.4.99.41	Transferred entry: 3.4.24.64
+3.4.99.42	Deleted entry
+3.4.99.43	Transferred entry: 3.4.23.42
+3.4.99.44	Transferred entry: 3.4.24.55
+3.4.99.45	Transferred entry: 3.4.24.56
+3.4.99.46	Transferred entry: 3.4.25.1
+3.5.1.1	Asparaginase
+3.5.1.2	Glutaminase
+3.5.1.3	Omega-amidase
+3.5.1.4	Amidase
+3.5.1.5	Urease
+3.5.1.6	Beta-ureidopropionase
+3.5.1.7	Ureidosuccinase
+3.5.1.8	Formylaspartate deformylase
+3.5.1.9	Arylformamidase
+3.5.1.10	Formyltetrahydrofolate deformylase
+3.5.1.11	Penicillin amidase
+3.5.1.12	Biotinidase
+3.5.1.13	Aryl-acylamidase
+3.5.1.14	N-acyl-aliphatic-L-amino acid amidohydrolase
+3.5.1.15	Aspartoacylase
+3.5.1.16	Acetylornithine deacetylase
+3.5.1.17	Acyl-lysine deacylase
+3.5.1.18	Succinyl-diaminopimelate desuccinylase
+3.5.1.19	Nicotinamidase
+3.5.1.20	Citrullinase
+3.5.1.21	N-acetyl-beta-alanine deacetylase
+3.5.1.22	Pantothenase
+3.5.1.23	Ceramidase
+3.5.1.24	Choloylglycine hydrolase
+3.5.1.25	N-acetylglucosamine-6-phosphate deacetylase
+3.5.1.26	N(4)-(beta-N-acetylglucosaminyl)-L-asparaginase
+3.5.1.27	Deleted entry
+3.5.1.28	N-acetylmuramoyl-L-alanine amidase
+3.5.1.29	2-(acetamidomethylene)succinate hydrolase
+3.5.1.30	5-aminopentanamidase
+3.5.1.31	Formylmethionine deformylase
+3.5.1.32	Hippurate hydrolase
+3.5.1.33	N-acetylglucosamine deacetylase
+3.5.1.34	Transferred entry: 3.4.13.5
+3.5.1.35	D-glutaminase
+3.5.1.36	N-methyl-2-oxoglutaramate hydrolase
+3.5.1.37	Transferred entry: 3.5.1.26
+3.5.1.38	Glutamin-(asparagin-)ase
+3.5.1.39	Alkylamidase
+3.5.1.40	Acylagmatine amidase
+3.5.1.41	Chitin deacetylase
+3.5.1.42	Nicotinamide-nucleotide amidase
+3.5.1.43	Peptidyl-glutaminase
+3.5.1.44	Protein-glutamine glutaminase
+3.5.1.45	Transferred entry: 6.3.4.6
+3.5.1.46	6-aminohexanoate-oligomer exohydrolase
+3.5.1.47	N-acetyldiaminopimelate deacetylase
+3.5.1.48	Acetylspermidine deacetylase
+3.5.1.49	Formamidase
+3.5.1.50	Pentanamidase
+3.5.1.51	4-acetamidobutyryl-CoA deacetylase
+3.5.1.52	Peptide-N(4)-(N-acetyl-beta-glucosaminyl)asparagine amidase
+3.5.1.53	N-carbamoylputrescine amidase
+3.5.1.54	Allophanate hydrolase
+3.5.1.55	Long-chain-fatty-acyl-glutamate deacylase
+3.5.1.56	N,N-dimethylformamidase
+3.5.1.57	Tryptophanamidase
+3.5.1.58	N-benzyloxycarbonylglycine hydrolase
+3.5.1.59	N-carbamoylsarcosine amidase
+3.5.1.60	N-(long-chain-acyl)ethanolamine deacylase
+3.5.1.61	Mimosinase
+3.5.1.62	Acetylputrescine deacetylase
+3.5.1.63	4-acetamidobutyrate deacetylase
+3.5.1.64	N(alpha)-benzyloxycarbonylleucine hydrolase
+3.5.1.65	Theanine hydrolase
+3.5.1.66	2-(hydroxymethyl)-3-(acetamidomethylene)succinate hydrolase
+3.5.1.67	4-methyleneglutaminase
+3.5.1.68	N-formylglutamate deformylase
+3.5.1.69	Glycosphingolipid deacylase
+3.5.1.70	Aculeacin-A deacylase
+3.5.1.71	N-feruloylglycine deacylase
+3.5.1.72	D-benzoylarginine-4-nitroanilide amidase
+3.5.1.73	Carnitinamidase
+3.5.1.74	Chenodeoxycholoyltaurine hydrolase
+3.5.1.75	Urethanase
+3.5.1.76	Arylalkyl acylamidase
+3.5.1.77	N-carbamoyl-D-amino-acid hydrolase
+3.5.1.78	Glutathionylspermidine amidase
+3.5.1.79	Phthalyl amidase
+3.5.1.80	Transferred entry: 3.5.1.25
+3.5.1.81	N-acyl-D-amino-acid deacylase
+3.5.1.82	N-acyl-D-glutamate deacylase
+3.5.1.83	N-acyl-D-aspartate deacylase
+3.5.1.84	Biuret amidohydrolase
+3.5.1.85	(S)-N-acetyl-1-phenylethylamine hydrolase
+3.5.1.86	Mandelamide amidase
+3.5.1.87	N-carbamoyl-L-amino-acid hydrolase
+3.5.1.88	Peptide deformylase
+3.5.1.89	N-acetylglucosaminylphosphatidylinositol deacetylase
+3.5.1.90	Adenosylcobinamide hydrolase
+3.5.1.91	N-substituted formamide deformylase
+3.5.1.92	Pantetheine hydrolase
+3.5.1.93	Glutaryl-7-aminocephalosporanic-acid acylase
+3.5.1.94	Gamma-glutamyl-gamma-aminobutyrate hydrolase
+3.5.1.95	N-malonylurea hydrolase
+3.5.1.96	Succinylglutamate desuccinylase
+3.5.1.97	Acyl-homoserine-lactone acylase
+3.5.1.98	Histone deacetylase
+3.5.1.99	Fatty acid amide hydrolase
+3.5.1.100	(R)-amidase
+3.5.1.101	L-proline amide hydrolase
+3.5.1.102	deformylase
+3.5.1.103	deacetylase
+3.5.1.104	Peptidoglycan-N-acetylglucosamine deacetylase
+3.5.1.105	Chitin disaccharide deacetylase
+3.5.1.106	N-formylmaleamate deformylase
+3.5.1.107	Maleamate amidohydrolase
+3.5.1.108	UDP-3-O-acyl-N-acetylglucosamine deacetylase
+3.5.1.109	Sphingomyelin deacylase
+3.5.1.110	Peroxyureidoacrylate/ureidoacrylate amidohydrolase
+3.5.1.111	2-oxoglutaramate amidase
+3.5.1.112	2'-N-acetylparomamine deacetylase
+3.5.1.113	2'''-acetyl-6'''-hydroxyneomycin C deacetylase
+3.5.1.114	N-acyl-aromatic-L-amino acid amidohydrolase
+3.5.1.115	Mycothiol S-conjugate amidase
+3.5.1.116	Ureidoglycolate amidohydrolase
+3.5.1.117	6-aminohexanoate-oligomer endohydrolase
+3.5.1.118	Gamma-glutamyl hercynylcysteine S-oxide hydrolase
+3.5.1.119	Pup amidohydrolase
+3.5.2.1	Barbiturase
+3.5.2.2	Dihydropyrimidinase
+3.5.2.3	Dihydroorotase
+3.5.2.4	Carboxymethylhydantoinase
+3.5.2.5	Allantoinase
+3.5.2.6	Beta-lactamase
+3.5.2.7	Imidazolonepropionase
+3.5.2.8	Transferred entry: 3.5.2.6
+3.5.2.9	5-oxoprolinase (ATP-hydrolyzing)
+3.5.2.10	Creatininase
+3.5.2.11	L-lysine-lactamase
+3.5.2.12	6-aminohexanoate-cyclic-dimer hydrolase
+3.5.2.13	2,5-dioxopiperazine hydrolase
+3.5.2.14	N-methylhydantoinase (ATP-hydrolyzing)
+3.5.2.15	Cyanuric acid amidohydrolase
+3.5.2.16	Maleimide hydrolase
+3.5.2.17	Hydroxyisourate hydrolase
+3.5.2.18	Enamidase
+3.5.2.19	Streptothricin hydrolase
+3.5.2.20	Isatin hydrolase
+3.5.3.1	Arginase
+3.5.3.2	Guanidinoacetase
+3.5.3.3	Creatinase
+3.5.3.4	Allantoicase
+3.5.3.5	Formimidoylaspartate deiminase
+3.5.3.6	Arginine deiminase
+3.5.3.7	Guanidinobutyrase
+3.5.3.8	Formimidoylglutamase
+3.5.3.9	Allantoate deiminase
+3.5.3.10	D-arginase
+3.5.3.11	Agmatinase
+3.5.3.12	Agmatine deiminase
+3.5.3.13	Formimidoylglutamate deiminase
+3.5.3.14	Amidinoaspartase
+3.5.3.15	Protein-arginine deiminase
+3.5.3.16	Methylguanidinase
+3.5.3.17	Guanidinopropionase
+3.5.3.18	Dimethylargininase
+3.5.3.19	Transferred entry: 3.5.1.116
+3.5.3.20	Diguanidinobutanase
+3.5.3.21	Methylenediurea deaminase
+3.5.3.22	Proclavaminate amidinohydrolase
+3.5.3.23	N-succinylarginine dihydrolase
+3.5.3.24	N(1)-aminopropylagmatine ureohydrolase
+3.5.3.25	N(omega)-hydroxy-L-arginine amidinohydrolase
+3.5.3.26	(S)-ureidoglycine aminohydrolase
+3.5.4.1	Cytosine deaminase
+3.5.4.2	Adenine deaminase
+3.5.4.3	Guanine deaminase
+3.5.4.4	Adenosine deaminase
+3.5.4.5	Cytidine deaminase
+3.5.4.6	AMP deaminase
+3.5.4.7	ADP deaminase
+3.5.4.8	Aminoimidazolase
+3.5.4.9	Methenyltetrahydrofolate cyclohydrolase
+3.5.4.10	IMP cyclohydrolase
+3.5.4.11	Pterin deaminase
+3.5.4.12	dCMP deaminase
+3.5.4.13	dCTP deaminase
+3.5.4.14	Transferred entry: 3.5.4.5
+3.5.4.15	Guanosine deaminase
+3.5.4.16	GTP cyclohydrolase I
+3.5.4.17	Adenosine-phosphate deaminase
+3.5.4.18	ATP deaminase
+3.5.4.19	Phosphoribosyl-AMP cyclohydrolase
+3.5.4.20	Pyrithiamine deaminase
+3.5.4.21	Creatinine deaminase
+3.5.4.22	1-pyrroline-4-hydroxy-2-carboxylate deaminase
+3.5.4.23	Blasticidin-S deaminase
+3.5.4.24	Sepiapterin deaminase
+3.5.4.25	GTP cyclohydrolase II
+3.5.4.26	Diaminohydroxyphosphoribosylaminopyrimidine deaminase
+3.5.4.27	Methenyltetrahydromethanopterin cyclohydrolase
+3.5.4.28	S-adenosylhomocysteine deaminase
+3.5.4.29	GTP cyclohydrolase IIa
+3.5.4.30	dCTP deaminase (dUMP-forming)
+3.5.4.31	S-methyl-5'-thioadenosine deaminase
+3.5.4.32	8-oxoguanine deaminase
+3.5.4.33	tRNA(adenine(34)) deaminase
+3.5.4.34	tRNA(Ala)(adenine(37)) deaminase
+3.5.4.35	tRNA(cytosine(8)) deaminase
+3.5.4.36	mRNA(cytosine(6666)) deaminase
+3.5.4.37	Double-stranded RNA adenine deaminase
+3.5.4.38	Single-stranded DNA cytosine deaminase
+3.5.4.39	GTP cyclohydrolase IV
+3.5.4.40	Aminodeoxyfutalosine deaminase
+3.5.4.41	5'-deoxyadenosine deaminase
+3.5.5.1	Nitrilase
+3.5.5.2	Ricinine nitrilase
+3.5.5.3	Transferred entry: 4.2.1.104
+3.5.5.4	Cyanoalanine nitrilase
+3.5.5.5	Arylacetonitrilase
+3.5.5.6	Bromoxynil nitrilase
+3.5.5.7	Aliphatic nitrilase
+3.5.5.8	Thiocyanate hydrolase
+3.5.99.1	Riboflavinase
+3.5.99.2	Aminopyrimidine aminohydrolase
+3.5.99.3	Hydroxydechloroatrazine ethylaminohydrolase
+3.5.99.4	N-isopropylammelide isopropylaminohydrolase
+3.5.99.5	2-aminomuconate deaminase
+3.5.99.6	Glucosamine-6-phosphate deaminase
+3.5.99.7	1-aminocyclopropane-1-carboxylate deaminase
+3.5.99.8	5-nitroanthranilic acid aminohydrolase
+3.5.99.9	2-nitroimidazole nitrohydrolase
+3.5.99.10	2-iminobutanoate/2-iminopropanoate deaminase
+3.6.1.1	Inorganic diphosphatase
+3.6.1.2	Trimetaphosphatase
+3.6.1.3	Adenosinetriphosphatase
+3.6.1.4	Transferred entry: 3.6.1.3
+3.6.1.5	Apyrase
+3.6.1.6	Nucleoside diphosphate phosphatase
+3.6.1.7	Acylphosphatase
+3.6.1.8	ATP diphosphatase
+3.6.1.9	Nucleotide diphosphatase
+3.6.1.10	Endopolyphosphatase
+3.6.1.11	Exopolyphosphatase
+3.6.1.12	dCTP diphosphatase
+3.6.1.13	ADP-ribose diphosphatase
+3.6.1.14	Adenosine-tetraphosphatase
+3.6.1.15	Nucleoside-triphosphate phosphatase
+3.6.1.16	CDP-glycerol diphosphatase
+3.6.1.17	Bis(5'-nucleosyl)-tetraphosphatase (asymmetrical)
+3.6.1.18	FAD diphosphatase
+3.6.1.19	Nucleoside-triphosphate diphosphatase
+3.6.1.20	5'-acylphosphoadenosine hydrolase
+3.6.1.21	ADP-sugar diphosphatase
+3.6.1.22	NAD(+) diphosphatase
+3.6.1.23	dUTP diphosphatase
+3.6.1.24	Nucleoside phosphoacylhydrolase
+3.6.1.25	Triphosphatase
+3.6.1.26	CDP-diacylglycerol diphosphatase
+3.6.1.27	Undecaprenyl-diphosphate phosphatase
+3.6.1.28	Thiamine-triphosphatase
+3.6.1.29	Bis(5'-adenosyl)-triphosphatase
+3.6.1.30	Transferred entry: 3.6.1.59 and 3.6.1.62
+3.6.1.31	Phosphoribosyl-ATP diphosphatase
+3.6.1.32	Transferred entry: 3.6.4.1
+3.6.1.33	Transferred entry: 3.6.4.2
+3.6.1.34	Transferred entry: 3.6.3.14
+3.6.1.35	Transferred entry: 3.6.3.6
+3.6.1.36	Transferred entry: 3.6.3.10
+3.6.1.37	Transferred entry: 3.6.3.9
+3.6.1.38	Transferred entry: 3.6.3.8
+3.6.1.39	Thymidine-triphosphatase
+3.6.1.40	Guanosine-5'-triphosphate,3'-diphosphate diphosphatase
+3.6.1.41	Bis(5'-nucleosyl)-tetraphosphatase (symmetrical)
+3.6.1.42	Guanosine-diphosphatase
+3.6.1.43	Dolichyldiphosphatase
+3.6.1.44	Oligosaccharide-diphosphodolichol diphosphatase
+3.6.1.45	UDP-sugar diphosphatase
+3.6.1.46	Transferred entry: 3.6.5.1
+3.6.1.47	Transferred entry: 3.6.5.2
+3.6.1.48	Transferred entry: 3.6.5.3
+3.6.1.49	Transferred entry: 3.6.5.4
+3.6.1.50	Transferred entry: 3.6.5.5
+3.6.1.51	Transferred entry: 3.6.5.6
+3.6.1.52	Diphosphoinositol-polyphosphate diphosphatase
+3.6.1.53	Mn(2+)-dependent ADP-ribose/CDP-alcohol diphosphatase
+3.6.1.54	UDP-2,3-diacylglucosamine diphosphatase
+3.6.1.55	8-oxo-dGTP diphosphatase
+3.6.1.56	2-hydroxy-dATP diphosphatase
+3.6.1.57	UDP-2,4-diacetamido-2,4,6-trideoxy-beta-L-altropyranose hydrolase
+3.6.1.58	8-oxo-dGDP phosphatase
+3.6.1.59	5'-(N(7)-methyl 5'-triphosphoguanosine)-[mRNA] diphosphatase
+3.6.1.60	Diadenosine hexaphosphate hydrolase (AMP-forming)
+3.6.1.61	Diadenosine hexaphosphate hydrolase (ATP-forming)
+3.6.1.62	5'-(N(7)-methylguanosine 5'-triphospho)-[mRNA] hydrolase
+3.6.1.63	Alpha-D-ribose 1-methylphosphonate 5-triphosphate diphosphatase
+3.6.1.64	Inosine diphosphate phosphatase
+3.6.1.65	(d)CTP diphosphatase
+3.6.1.66	XTP/dITP diphosphatase
+3.6.1.67	Dihydroneopterin triphosphate diphosphatase
+3.6.2.1	Adenylylsulfatase
+3.6.2.2	Phosphoadenylylsulfatase
+3.6.3.1	Phospholipid-translocating ATPase
+3.6.3.2	Magnesium-importing ATPase
+3.6.3.3	Cadmium-exporting ATPase
+3.6.3.4	Cu(2+)-exporting ATPase
+3.6.3.5	Zinc-exporting ATPase
+3.6.3.6	Proton-exporting ATPase
+3.6.3.7	Sodium-exporting ATPase
+3.6.3.8	Calcium-transporting ATPase
+3.6.3.9	Sodium/potassium-exchanging ATPase
+3.6.3.10	Hydrogen/potassium-exchanging ATPase
+3.6.3.11	Chloride-transporting ATPase
+3.6.3.12	Potassium-transporting ATPase
+3.6.3.13	Transferred entry: 3.6.3.1
+3.6.3.14	H(+)-transporting two-sector ATPase
+3.6.3.15	Sodium-transporting two-sector ATPase
+3.6.3.16	Arsenite-transporting ATPase
+3.6.3.17	Monosaccharide-transporting ATPase
+3.6.3.18	Oligosaccharide-transporting ATPase
+3.6.3.19	Maltose-transporting ATPase
+3.6.3.20	Glycerol-3-phosphate-transporting ATPase
+3.6.3.21	Polar-amino-acid-transporting ATPase
+3.6.3.22	Nonpolar-amino-acid-transporting ATPase
+3.6.3.23	Oligopeptide-transporting ATPase
+3.6.3.24	Nickel-transporting ATPase
+3.6.3.25	Sulfate-transporting ATPase
+3.6.3.26	Nitrate-transporting ATPase
+3.6.3.27	Phosphate-transporting ATPase
+3.6.3.28	Phosphonate-transporting ATPase
+3.6.3.29	Molybdate-transporting ATPase
+3.6.3.30	Fe(3+)-transporting ATPase
+3.6.3.31	Polyamine-transporting ATPase
+3.6.3.32	Quaternary-amine-transporting ATPase
+3.6.3.33	Vitamin B12-transporting ATPase
+3.6.3.34	Iron-chelate-transporting ATPase
+3.6.3.35	Manganese-transporting ATPase
+3.6.3.36	Taurine-transporting ATPase
+3.6.3.37	Guanine-transporting ATPase
+3.6.3.38	Capsular-polysaccharide-transporting ATPase
+3.6.3.39	Lipopolysaccharide-transporting ATPase
+3.6.3.40	Teichoic-acid-transporting ATPase
+3.6.3.41	Heme-transporting ATPase
+3.6.3.42	Beta-glucan-transporting ATPase
+3.6.3.43	Peptide-transporting ATPase
+3.6.3.44	Xenobiotic-transporting ATPase
+3.6.3.45	Transferred entry: 3.6.3.44
+3.6.3.46	Cadmium-transporting ATPase
+3.6.3.47	Fatty-acyl-CoA-transporting ATPase
+3.6.3.48	Alpha-factor-transporting ATPase
+3.6.3.49	Channel-conductance-controlling ATPase
+3.6.3.50	Protein-secreting ATPase
+3.6.3.51	Mitochondrial protein-transporting ATPase
+3.6.3.52	Chloroplast protein-transporting ATPase
+3.6.3.53	Ag(+)-exporting ATPase
+3.6.3.54	Cu(+) exporting ATPase
+3.6.3.55	Tungstate-importing ATPase
+3.6.4.1	Myosin ATPase
+3.6.4.2	Dynein ATPase
+3.6.4.3	Microtubule-severing ATPase
+3.6.4.4	Plus-end-directed kinesin ATPase
+3.6.4.5	Minus-end-directed kinesin ATPase
+3.6.4.6	Vesicle-fusing ATPase
+3.6.4.7	Peroxisome-assembly ATPase
+3.6.4.8	Proteasome ATPase
+3.6.4.9	Chaperonin ATPase
+3.6.4.10	Non-chaperonin molecular chaperone ATPase
+3.6.4.11	Nucleoplasmin ATPase
+3.6.4.12	DNA helicase
+3.6.4.13	RNA helicase
+3.6.5.1	Heterotrimeric G-protein GTPase
+3.6.5.2	Small monomeric GTPase
+3.6.5.3	Protein-synthesizing GTPase
+3.6.5.4	Signal-recognition-particle GTPase
+3.6.5.5	Dynamin GTPase
+3.6.5.6	Tubulin GTPase
+3.7.1.1	Oxaloacetase
+3.7.1.2	Fumarylacetoacetase
+3.7.1.3	Kynureninase
+3.7.1.4	Phloretin hydrolase
+3.7.1.5	Acylpyruvate hydrolase
+3.7.1.6	Acetylpyruvate hydrolase
+3.7.1.7	Beta-diketone hydrolase
+3.7.1.8	2,6-dioxo-6-phenylhexa-3-enoate hydrolase
+3.7.1.9	2-hydroxymuconate-6-semialdehyde hydrolase
+3.7.1.10	Cyclohexane-1,3-dione hydrolase
+3.7.1.11	Cyclohexane-1,2-dione hydrolase
+3.7.1.12	Cobalt-precorrin 5A hydrolase
+3.7.1.13	2-hydroxy-6-oxo-6-(2-aminophenyl)hexa-2,4-dienoate hydrolase
+3.7.1.14	2-hydroxy-6-oxonona-2,4-dienedioate hydrolase
+3.7.1.15	Transferred entry: 4.2.1.138
+3.7.1.16	Transferred entry: 3.3.2.12
+3.7.1.17	hydrolase
+3.7.1.18	6-oxocamphor hydrolase
+3.7.1.19	2,6-dihydroxypseudooxynicotine hydrolase
+3.7.1.20	3-fumarylpyruvate hydrolase
+3.7.1.21	6-oxocyclohex-1-ene-1-carbonyl-CoA hydratase
+3.7.1.22	3D-(3,5/4)-trihydroxycyclohexane-1,2-dione acylhydrolase (decyclizing)
+3.8.1.1	Alkylhalidase
+3.8.1.2	(S)-2-haloacid dehalogenase
+3.8.1.3	Haloacetate dehalogenase
+3.8.1.4	Transferred entry: 1.21.99.4
+3.8.1.5	Haloalkane dehalogenase
+3.8.1.6	4-chlorobenzoate dehalogenase
+3.8.1.7	4-chlorobenzoyl-CoA dehalogenase
+3.8.1.8	Atrazine chlorohydrolase
+3.8.1.9	(R)-2-haloacid dehalogenase
+3.8.1.10	2-haloacid dehalogenase (configuration-inverting)
+3.8.1.11	2-haloacid dehalogenase (configuration-retaining)
+3.8.2.1	Transferred entry: 3.1.8.2
+3.9.1.1	Phosphoamidase
+3.9.1.2	Protein arginine phosphatase
+3.10.1.1	N-sulfoglucosamine sulfohydrolase
+3.10.1.2	Cyclamate sulfohydrolase
+3.11.1.1	Phosphonoacetaldehyde hydrolase
+3.11.1.2	Phosphonoacetate hydrolase
+3.11.1.3	Phosphonopyruvate hydrolase
+3.12.1.1	Trithionate hydrolase
+3.13.1.1	UDP-sulfoquinovose synthase
+3.13.1.2	Deleted entry
+3.13.1.3	2'-hydroxybiphenyl-2-sulfinate desulfinase
+3.13.1.4	3-sulfinopropanoyl-CoA desulfinase
+4.1.1.1	Pyruvate decarboxylase
+4.1.1.2	Oxalate decarboxylase
+4.1.1.3	Oxaloacetate decarboxylase
+4.1.1.4	Acetoacetate decarboxylase
+4.1.1.5	Acetolactate decarboxylase
+4.1.1.6	Aconitate decarboxylase
+4.1.1.7	Benzoylformate decarboxylase
+4.1.1.8	Oxalyl-CoA decarboxylase
+4.1.1.9	Malonyl-CoA decarboxylase
+4.1.1.10	Transferred entry: 4.1.1.12
+4.1.1.11	Aspartate 1-decarboxylase
+4.1.1.12	Aspartate 4-decarboxylase
+4.1.1.13	Deleted entry
+4.1.1.14	Valine decarboxylase
+4.1.1.15	Glutamate decarboxylase
+4.1.1.16	Hydroxyglutamate decarboxylase
+4.1.1.17	Ornithine decarboxylase
+4.1.1.18	Lysine decarboxylase
+4.1.1.19	Arginine decarboxylase
+4.1.1.20	Diaminopimelate decarboxylase
+4.1.1.21	Phosphoribosylaminoimidazole carboxylase
+4.1.1.22	Histidine decarboxylase
+4.1.1.23	Orotidine-5'-phosphate decarboxylase
+4.1.1.24	Aminobenzoate decarboxylase
+4.1.1.25	Tyrosine decarboxylase
+4.1.1.26	Transferred entry: 4.1.1.28
+4.1.1.27	Transferred entry: 4.1.1.28
+4.1.1.28	Aromatic-L-amino-acid decarboxylase
+4.1.1.29	Sulfinoalanine decarboxylase
+4.1.1.30	Pantothenoylcysteine decarboxylase
+4.1.1.31	Phosphoenolpyruvate carboxylase
+4.1.1.32	Phosphoenolpyruvate carboxykinase (GTP)
+4.1.1.33	Diphosphomevalonate decarboxylase
+4.1.1.34	Dehydro-L-gulonate decarboxylase
+4.1.1.35	UDP-glucuronate decarboxylase
+4.1.1.36	Phosphopantothenoylcysteine decarboxylase
+4.1.1.37	Uroporphyrinogen decarboxylase
+4.1.1.38	Phosphoenolpyruvate carboxykinase (diphosphate)
+4.1.1.39	Ribulose-bisphosphate carboxylase
+4.1.1.40	Hydroxypyruvate decarboxylase
+4.1.1.41	Methylmalonyl-CoA decarboxylase
+4.1.1.42	Carnitine decarboxylase
+4.1.1.43	Phenylpyruvate decarboxylase
+4.1.1.44	4-carboxymuconolactone decarboxylase
+4.1.1.45	Aminocarboxymuconate-semialdehyde decarboxylase
+4.1.1.46	o-pyrocatechuate decarboxylase
+4.1.1.47	Tartronate-semialdehyde synthase
+4.1.1.48	Indole-3-glycerol-phosphate synthase
+4.1.1.49	Phosphoenolpyruvate carboxykinase (ATP)
+4.1.1.50	Adenosylmethionine decarboxylase
+4.1.1.51	3-hydroxy-2-methylpyridine-4,5-dicarboxylate 4-decarboxylase
+4.1.1.52	6-methylsalicylate decarboxylase
+4.1.1.53	Phenylalanine decarboxylase
+4.1.1.54	Dihydroxyfumarate decarboxylase
+4.1.1.55	4,5-dihydroxyphthalate decarboxylase
+4.1.1.56	3-oxolaurate decarboxylase
+4.1.1.57	Methionine decarboxylase
+4.1.1.58	Orsellinate decarboxylase
+4.1.1.59	Gallate decarboxylase
+4.1.1.60	Stipitatonate decarboxylase
+4.1.1.61	4-hydroxybenzoate decarboxylase
+4.1.1.62	Gentisate decarboxylase
+4.1.1.63	Protocatechuate decarboxylase
+4.1.1.64	2,2-dialkylglycine decarboxylase (pyruvate)
+4.1.1.65	Phosphatidylserine decarboxylase
+4.1.1.66	Uracil-5-carboxylate decarboxylase
+4.1.1.67	UDP-galacturonate decarboxylase
+4.1.1.68	5-oxopent-3-ene-1,2,5-tricarboxylate decarboxylase
+4.1.1.69	3,4-dihydroxyphthalate decarboxylase
+4.1.1.70	Glutaconyl-CoA decarboxylase
+4.1.1.71	2-oxoglutarate decarboxylase
+4.1.1.72	Branched-chain-2-oxoacid decarboxylase
+4.1.1.73	Tartrate decarboxylase
+4.1.1.74	Indolepyruvate decarboxylase
+4.1.1.75	5-guanidino-2-oxopentanoate decarboxylase
+4.1.1.76	Arylmalonate decarboxylase
+4.1.1.77	2-oxo-3-hexenedioate decarboxylase
+4.1.1.78	Acetylenedicarboxylate decarboxylase
+4.1.1.79	Sulfopyruvate decarboxylase
+4.1.1.80	4-hydroxyphenylpyruvate decarboxylase
+4.1.1.81	Threonine-phosphate decarboxylase
+4.1.1.82	Phosphonopyruvate decarboxylase
+4.1.1.83	4-hydroxyphenylacetate decarboxylase
+4.1.1.84	D-dopachrome decarboxylase
+4.1.1.85	3-dehydro-L-gulonate-6-phosphate decarboxylase
+4.1.1.86	Diaminobutyrate decarboxylase
+4.1.1.87	Malonyl-S-ACP decarboxylase
+4.1.1.88	Biotin-independent malonate decarboxylase
+4.1.1.89	Biotin-dependent malonate decarboxylase
+4.1.1.90	Peptidyl-glutamate 4-carboxylase
+4.1.1.91	Salicylate decarboxylase
+4.1.1.92	Indole-3-carboxylate decarboxylase
+4.1.1.93	Pyrrole-2-carboxylate decarboxylase
+4.1.1.94	Ethylmalonyl-CoA decarboxylase
+4.1.1.95	L-glutamyl-[BtrI acyl-carrier protein] decarboxylase
+4.1.1.96	Carboxynorspermidine decarboxylase
+4.1.1.97	2-oxo-4-hydroxy-4-carboxy-5-ureidoimidazoline decarboxylase
+4.1.1.98	4-hydroxy-3-polyprenylbenzoate decarboxylase
+4.1.1.99	Phosphomevalonate decarboxylase
+4.1.1.100	Prephenate decarboxylase
+4.1.1.101	Malolactic enzyme
+4.1.1.102	Phenacrylate decarboxylase
+4.1.2.1	Transferred entry: 4.1.3.16
+4.1.2.2	Ketotetrose-phosphate aldolase
+4.1.2.3	Deleted entry
+4.1.2.4	Deoxyribose-phosphate aldolase
+4.1.2.5	L-threonine aldolase
+4.1.2.6	Deleted entry
+4.1.2.7	Transferred entry: 4.1.2.13
+4.1.2.8	Indole-3-glycerol-phosphate lyase
+4.1.2.9	Phosphoketolase
+4.1.2.10	(R)-mandelonitrile lyase
+4.1.2.11	Hydroxymandelonitrile lyase
+4.1.2.12	2-dehydropantoate aldolase
+4.1.2.13	Fructose-bisphosphate aldolase
+4.1.2.14	2-dehydro-3-deoxy-phosphogluconate aldolase
+4.1.2.15	Transferred entry: 2.5.1.54
+4.1.2.16	Transferred entry: 2.5.1.55
+4.1.2.17	L-fuculose-phosphate aldolase
+4.1.2.18	2-dehydro-3-deoxy-L-pentonate aldolase
+4.1.2.19	Rhamnulose-1-phosphate aldolase
+4.1.2.20	2-dehydro-3-deoxyglucarate aldolase
+4.1.2.21	2-dehydro-3-deoxy-6-phosphogalactonate aldolase
+4.1.2.22	Fructose-6-phosphate phosphoketolase
+4.1.2.23	3-deoxy-D-manno-octulosonate aldolase
+4.1.2.24	Dimethylaniline-N-oxide aldolase
+4.1.2.25	Dihydroneopterin aldolase
+4.1.2.26	Phenylserine aldolase
+4.1.2.27	Sphinganine-1-phosphate aldolase
+4.1.2.28	2-dehydro-3-deoxy-D-pentonate aldolase
+4.1.2.29	5-dehydro-2-deoxyphosphogluconate aldolase
+4.1.2.30	17-alpha-hydroxyprogesterone aldolase
+4.1.2.31	Transferred entry: 4.1.3.16
+4.1.2.32	Trimethylamine-oxide aldolase
+4.1.2.33	Fucosterol-epoxide lyase
+4.1.2.34	4-(2-carboxyphenyl)-2-oxobut-3-enoate aldolase
+4.1.2.35	Propioin synthase
+4.1.2.36	Lactate aldolase
+4.1.2.37	Transferred entry: 4.1.2.46 and 4.1.2.47
+4.1.2.38	Benzoin aldolase
+4.1.2.39	Transferred entry: 4.1.2.46 and 4.1.2.47
+4.1.2.40	Tagatose-bisphosphate aldolase
+4.1.2.41	Vanillin synthase
+4.1.2.42	D-threonine aldolase
+4.1.2.43	3-hexulose-6-phosphate synthase
+4.1.2.44	2,3-epoxybenzoyl-CoA dihydrolase
+4.1.2.45	Trans-o-hydroxybenzylidenepyruvate hydratase-aldolase
+4.1.2.46	Aliphatic (R)-hydroxynitrile lyase
+4.1.2.47	(S)-hydroxynitrile lyase
+4.1.2.48	Low-specificity L-threonine aldolase
+4.1.2.49	L-allo-threonine aldolase
+4.1.2.50	6-carboxytetrahydropterin synthase
+4.1.2.51	2-dehydro-3-deoxy-D-gluconate aldolase
+4.1.2.52	4-hydroxy-2-oxoheptanedioate aldolase
+4.1.2.53	2-keto-3-deoxy-L-rhamnonate aldolase
+4.1.2.54	L-threo-3-deoxy-hexylosonate aldolase
+4.1.2.55	aldolase
+4.1.2.56	2-amino-4,5-dihydroxy-6-oxo-7-(phosphonooxy)heptanoate synthase
+4.1.2.57	Sulfofructosephosphate aldolase
+4.1.3.1	Isocitrate lyase
+4.1.3.2	Transferred entry: 2.3.3.9
+4.1.3.3	N-acetylneuraminate lyase
+4.1.3.4	Hydroxymethylglutaryl-CoA lyase
+4.1.3.5	Transferred entry: 2.3.3.10
+4.1.3.6	Citrate (pro-3S)-lyase
+4.1.3.7	Transferred entry: 2.3.3.1
+4.1.3.8	Transferred entry: 2.3.3.8
+4.1.3.9	Transferred entry: 2.3.3.11
+4.1.3.10	Transferred entry: 2.3.3.7
+4.1.3.11	Transferred entry: 2.3.3.12
+4.1.3.12	Transferred entry: 2.3.3.13
+4.1.3.13	Oxalomalate lyase
+4.1.3.14	L-erythro-3-hydroxyaspartate aldolase
+4.1.3.15	Transferred entry: 2.2.1.5
+4.1.3.16	4-hydroxy-2-oxoglutarate aldolase
+4.1.3.17	4-hydroxy-4-methyl-2-oxoglutarate aldolase
+4.1.3.18	Transferred entry: 2.2.1.6
+4.1.3.19	Transferred entry: 2.5.1.56
+4.1.3.20	Transferred entry: 2.5.1.57
+4.1.3.21	Transferred entry: 2.3.3.14
+4.1.3.22	Citramalate lyase
+4.1.3.23	Transferred entry: 2.3.3.2
+4.1.3.24	Malyl-CoA lyase
+4.1.3.25	(S)-citramalyl-CoA lyase
+4.1.3.26	3-hydroxy-3-isohexenylglutaryl-CoA lyase
+4.1.3.27	Anthranilate synthase
+4.1.3.28	Transferred entry: 2.3.3.3
+4.1.3.29	Transferred entry: 2.3.3.4
+4.1.3.30	Methylisocitrate lyase
+4.1.3.31	Transferred entry: 2.3.3.5
+4.1.3.32	2,3-dimethylmalate lyase
+4.1.3.33	Transferred entry: 2.3.3.6
+4.1.3.34	Citryl-CoA lyase
+4.1.3.35	(1-hydroxycyclohexan-1-yl)acetyl-CoA lyase
+4.1.3.36	1,4-dihydroxy-2-naphthoyl-CoA synthase
+4.1.3.37	Transferred entry: 2.2.1.7
+4.1.3.38	Aminodeoxychorismate lyase
+4.1.3.39	4-hydroxy-2-oxovalerate aldolase
+4.1.3.40	Chorismate lyase
+4.1.3.41	3-hydroxy-D-aspartate aldolase
+4.1.3.42	(4S)-4-hydroxy-2-oxoglutarate aldolase
+4.1.3.43	4-hydroxy-2-oxohexanoate aldolase
+4.1.3.44	tRNA 4-demethylwyosine synthase (AdoMet-dependent)
+4.1.3.45	3-hydroxybenzoate synthase
+4.1.3.46	(R)-citramalyl-CoA lyase
+4.1.99.1	Tryptophanase
+4.1.99.2	Tyrosine phenol-lyase
+4.1.99.3	Deoxyribodipyrimidine photo-lyase
+4.1.99.4	Transferred entry: 3.5.99.7
+4.1.99.5	Aldehyde oxygenase (deformylating)
+4.1.99.6	Transferred entry: 4.2.3.6
+4.1.99.7	Transferred entry: 4.2.3.9
+4.1.99.8	Transferred entry: 4.2.3.119 and 4.2.3.120
+4.1.99.9	Transferred entry: 4.2.3.15
+4.1.99.10	Transferred entry: 4.2.3.16
+4.1.99.11	Benzylsuccinate synthase
+4.1.99.12	3,4-dihydroxy-2-butanone-4-phosphate synthase
+4.1.99.13	(6-4)DNA photolyase
+4.1.99.14	Spore photoproduct lyase
+4.1.99.15	Deleted entry
+4.1.99.16	Geosmin synthase
+4.1.99.17	Phosphomethylpyrimidine synthase
+4.1.99.18	Cyclic pyranopterin phosphate synthase
+4.1.99.19	2-iminoacetate synthase
+4.1.99.20	3-amino-4-hydroxybenzoate synthase
+4.1.99.21	Transferred entry: 4.2.3.153
+4.2.1.1	Carbonate dehydratase
+4.2.1.2	Fumarate hydratase
+4.2.1.3	Aconitate hydratase
+4.2.1.4	Transferred entry: 4.2.1.3
+4.2.1.5	Arabinonate dehydratase
+4.2.1.6	Galactonate dehydratase
+4.2.1.7	Altronate dehydratase
+4.2.1.8	Mannonate dehydratase
+4.2.1.9	Dihydroxy-acid dehydratase
+4.2.1.10	3-dehydroquinate dehydratase
+4.2.1.11	Phosphopyruvate hydratase
+4.2.1.12	Phosphogluconate dehydratase
+4.2.1.13	Transferred entry: 4.3.1.17
+4.2.1.14	Transferred entry: 4.3.1.18
+4.2.1.15	Transferred entry: 4.4.1.1
+4.2.1.16	Transferred entry: 4.3.1.19
+4.2.1.17	Enoyl-CoA hydratase
+4.2.1.18	Methylglutaconyl-CoA hydratase
+4.2.1.19	Imidazoleglycerol-phosphate dehydratase
+4.2.1.20	Tryptophan synthase
+4.2.1.21	Transferred entry: 4.2.1.22
+4.2.1.22	Cystathionine beta-synthase
+4.2.1.23	Deleted entry
+4.2.1.24	Porphobilinogen synthase
+4.2.1.25	L-arabinonate dehydratase
+4.2.1.26	Transferred entry: 4.3.1.9
+4.2.1.27	Acetylenecarboxylate hydratase
+4.2.1.28	Propanediol dehydratase
+4.2.1.29	Transferred entry: 4.99.1.6
+4.2.1.30	Glycerol dehydratase
+4.2.1.31	Maleate hydratase
+4.2.1.32	L(+)-tartrate dehydratase
+4.2.1.33	3-isopropylmalate dehydratase
+4.2.1.34	(S)-2-methylmalate dehydratase
+4.2.1.35	(R)-2-methylmalate dehydratase
+4.2.1.36	Homoaconitate hydratase
+4.2.1.37	Transferred entry: 3.3.2.4
+4.2.1.38	Transferred entry: 4.3.1.20
+4.2.1.39	Gluconate dehydratase
+4.2.1.40	Glucarate dehydratase
+4.2.1.41	5-dehydro-4-deoxyglucarate dehydratase
+4.2.1.42	Galactarate dehydratase
+4.2.1.43	2-dehydro-3-deoxy-L-arabinonate dehydratase
+4.2.1.44	Myo-inosose-2 dehydratase
+4.2.1.45	CDP-glucose 4,6-dehydratase
+4.2.1.46	dTDP-glucose 4,6-dehydratase
+4.2.1.47	GDP-mannose 4,6-dehydratase
+4.2.1.48	D-glutamate cyclase
+4.2.1.49	Urocanate hydratase
+4.2.1.50	Pyrazolylalanine synthase
+4.2.1.51	Prephenate dehydratase
+4.2.1.52	Transferred entry: 4.3.3.7
+4.2.1.53	Oleate hydratase
+4.2.1.54	Lactoyl-CoA dehydratase
+4.2.1.55	3-hydroxybutyryl-CoA dehydratase
+4.2.1.56	Itaconyl-CoA hydratase
+4.2.1.57	Isohexenylglutaconyl-CoA hydratase
+4.2.1.58	Transferred entry: 4.2.1.59
+4.2.1.59	3-hydroxyacyl-[acyl-carrier-protein] dehydratase
+4.2.1.60	Transferred entry: 4.2.1.59
+4.2.1.61	Transferred entry: 4.2.1.59
+4.2.1.62	5-alpha-hydroxysteroid dehydratase
+4.2.1.63	Transferred entry: 3.3.2.9 and 3.3.2.10
+4.2.1.64	Transferred entry: 3.3.2.9 and 3.3.2.10
+4.2.1.65	3-cyanoalanine hydratase
+4.2.1.66	Cyanide hydratase
+4.2.1.67	D-fuconate dehydratase
+4.2.1.68	L-fuconate dehydratase
+4.2.1.69	Cyanamide hydratase
+4.2.1.70	Pseudouridylate synthase
+4.2.1.71	Transferred entry: 4.2.1.27
+4.2.1.72	Transferred entry: 4.1.1.78
+4.2.1.73	Protoaphin-aglucone dehydratase (cyclizing)
+4.2.1.74	Long-chain-enoyl-CoA hydratase
+4.2.1.75	Uroporphyrinogen-III synthase
+4.2.1.76	UDP-glucose 4,6-dehydratase
+4.2.1.77	Trans-L-3-hydroxyproline dehydratase
+4.2.1.78	(S)-norcoclaurine synthase
+4.2.1.79	2-methylcitrate dehydratase
+4.2.1.80	2-oxopent-4-enoate hydratase
+4.2.1.81	D(-)-tartrate dehydratase
+4.2.1.82	Xylonate dehydratase
+4.2.1.83	4-oxalmesaconate hydratase
+4.2.1.84	Nitrile hydratase
+4.2.1.85	Dimethylmaleate hydratase
+4.2.1.86	Transferred entry: 4.2.1.98
+4.2.1.87	Octopamine dehydratase
+4.2.1.88	(R)-synephrine
+4.2.1.89	Transferred entry: 2.8.3.21 and 4.2.1.149
+4.2.1.90	L-rhamnonate dehydratase
+4.2.1.91	Arogenate dehydratase
+4.2.1.92	Hydroperoxide dehydratase
+4.2.1.93	ATP-dependent NAD(P)H-hydrate dehydratase
+4.2.1.94	Scytalone dehydratase
+4.2.1.95	Kievitone hydratase
+4.2.1.96	4a-hydroxytetrahydrobiopterin dehydratase
+4.2.1.97	Phaseollidin hydratase
+4.2.1.98	16-alpha-hydroxyprogesterone dehydratase
+4.2.1.99	2-methylisocitrate dehydratase
+4.2.1.100	Cyclohexa-1,5-dienecarbonyl-CoA hydratase
+4.2.1.101	Trans-feruloyl-CoA hydratase
+4.2.1.102	Transferred entry: 4.2.1.100
+4.2.1.103	Cyclohexyl-isocyanide hydratase
+4.2.1.104	Cyanase
+4.2.1.105	2-hydroxyisoflavanone dehydratase
+4.2.1.106	Bile-acid 7-alpha-dehydratase
+4.2.1.107	hydratase
+4.2.1.108	Ectoine synthase
+4.2.1.109	Methylthioribulose 1-phosphate dehydratase
+4.2.1.110	Aldos-2-ulose dehydratase
+4.2.1.111	1,5-anhydro-D-fructose dehydratase
+4.2.1.112	Acetylene hydratase
+4.2.1.113	o-succinylbenzoate synthase
+4.2.1.114	Methanogen homoaconitase
+4.2.1.115	UDP-N-acetylglucosamine 4,6-dehydratase (inverting)
+4.2.1.116	3-hydroxypropionyl-CoA dehydratase
+4.2.1.117	2-methylcitrate dehydratase (2-methyl-trans-aconitate forming)
+4.2.1.118	3-dehydroshikimate dehydratase
+4.2.1.119	Enoyl-CoA hydratase 2
+4.2.1.120	4-hydroxybutanoyl-CoA dehydratase
+4.2.1.121	Colneleate synthase
+4.2.1.122	Tryptophan synthase (indole-salvaging)
+4.2.1.123	Tetrahymanol synthase
+4.2.1.124	Arabidiol synthase
+4.2.1.125	Dammarenediol II synthase
+4.2.1.126	N-acetylmuramic acid 6-phosphate etherase
+4.2.1.127	Linalool dehydratase
+4.2.1.128	Lupan-3-beta,20-diol synthase
+4.2.1.129	Squalene--hopanol cyclase
+4.2.1.130	D-lactate dehydratase
+4.2.1.131	Carotenoid 1,2-hydratase
+4.2.1.132	2-hydroxyhexa-2,4-dienoate hydratase
+4.2.1.133	Copal-8-ol diphosphate hydratase
+4.2.1.134	Very-long-chain (3R)-3-hydroxyacyl-CoA dehydratase
+4.2.1.135	UDP-N-acetylglucosamine 4,6-dehydratase (configuration-retaining)
+4.2.1.136	ADP-dependent NAD(P)H-hydrate dehydratase
+4.2.1.137	Sporulenol synthase
+4.2.1.138	(+)-caryolan-1-ol synthase
+4.2.1.139	Medicarpin synthase
+4.2.1.140	Gluconate/galactonate dehydratase
+4.2.1.141	2-dehydro-3-deoxy-D-arabinonate dehydratase
+4.2.1.142	5'-oxoaverantin cyclase
+4.2.1.143	Versicolorin B synthase
+4.2.1.144	3-amino-5-hydroxybenzoate synthase
+4.2.1.145	Capreomycidine synthase
+4.2.1.146	L-galactonate dehydratase
+4.2.1.147	5,6,7,8-tetrahydromethanopterin hydro-lyase
+4.2.1.148	2-methylfumaryl-CoA hydratase
+4.2.1.149	Crotonobetainyl-CoA hydratase
+4.2.1.150	Short-chain-enoyl-CoA hydratase
+4.2.1.151	Chorismate dehydratase
+4.2.1.152	Hydroperoxy icosatetraenoate dehydratase
+4.2.1.153	3-methylfumaryl-CoA hydratase
+4.2.1.154	Tetracenomycin F2 cyclase
+4.2.1.155	Methylthioacryloyl-CoA hydratase
+4.2.1.156	L-talarate dehydratase
+4.2.1.157	(R)-2-hydroxyisocaproyl-CoA dehydratase
+4.2.1.158	Galactarate dehydratase (D-threo-forming)
+4.2.1.159	dTDP-4-dehydro-6-deoxy-alpha-D-glucopyranose 2,3-dehydratase
+4.2.1.160	isomerase/dehydratase
+4.2.1.161	Bisanhydrobacterioruberin hydratase
+4.2.2.1	Hyaluronate lyase
+4.2.2.2	Pectate lyase
+4.2.2.3	Mannuronate-specific alginate lyase
+4.2.2.4	Transferred entry: 4.2.2.20 and 4.2.2.21
+4.2.2.5	Chondroitin AC lyase
+4.2.2.6	Oligogalacturonide lyase
+4.2.2.7	Heparin lyase
+4.2.2.8	Heparin-sulfate lyase
+4.2.2.9	Pectate disaccharide-lyase
+4.2.2.10	Pectin lyase
+4.2.2.11	Guluronate-specific alginate lyase
+4.2.2.12	Xanthan lyase
+4.2.2.13	Exo-(1->4)-alpha-D-glucan lyase
+4.2.2.14	Glucuronan lyase
+4.2.2.15	Anhydrosialidase
+4.2.2.16	Levan fructotransferase (DFA-IV-forming)
+4.2.2.17	Inulin fructotransferase (DFA-I-forming)
+4.2.2.18	Inulin fructotransferase (DFA-III-forming)
+4.2.2.19	Chondroitin B lyase
+4.2.2.20	Chondroitin-sulfate-ABC endolyase
+4.2.2.21	Chondroitin-sulfate-ABC exolyase
+4.2.2.22	Pectate trisaccharide-lyase
+4.2.2.23	Rhamnogalacturonan endolyase
+4.2.2.24	Rhamnogalacturonan exolyase
+4.2.2.25	Gellan lyase
+4.2.2.26	Oligo-alginate lyase
+4.2.3.1	Threonine synthase
+4.2.3.2	Ethanolamine-phosphate phospho-lyase
+4.2.3.3	Methylglyoxal synthase
+4.2.3.4	3-dehydroquinate synthase
+4.2.3.5	Chorismate synthase
+4.2.3.6	Trichodiene synthase
+4.2.3.7	Pentalenene synthase
+4.2.3.8	Casbene synthase
+4.2.3.9	Aristolochene synthase
+4.2.3.10	(-)-endo-fenchol synthase
+4.2.3.11	Sabinene-hydrate synthase
+4.2.3.12	6-pyruvoyltetrahydropterin synthase
+4.2.3.13	(+)-delta-cadinene synthase
+4.2.3.14	Transferred entry: 4.2.3.119 and 4.2.3.120
+4.2.3.15	Myrcene synthase
+4.2.3.16	(4S)-limonene synthase
+4.2.3.17	Taxadiene synthase
+4.2.3.18	Abieta-7,13-diene synthase
+4.2.3.19	Ent-kaurene synthase
+4.2.3.20	(R)-limonene synthase
+4.2.3.21	Vetispiradiene synthase
+4.2.3.22	Germacradienol synthase
+4.2.3.23	Germacrene-A synthase
+4.2.3.24	Amorpha-4,11-diene synthase
+4.2.3.25	S-linalool synthase
+4.2.3.26	R-linalool synthase
+4.2.3.27	Isoprene synthase
+4.2.3.28	Ent-cassa-12,15-diene synthase
+4.2.3.29	Ent-sandaracopimaradiene synthase
+4.2.3.30	Ent-pimara-8(14),15-diene synthase
+4.2.3.31	Ent-pimara-9(11),15-diene synthase
+4.2.3.32	Levopimaradiene synthase
+4.2.3.33	Stemar-13-ene synthase
+4.2.3.34	Stemod-13(17)-ene synthase
+4.2.3.35	Syn-pimara-7,15-diene synthase
+4.2.3.36	Terpentetriene synthase
+4.2.3.37	Epi-isozizaene synthase
+4.2.3.38	Alpha-bisabolene synthase
+4.2.3.39	Epi-cedrol synthase
+4.2.3.40	(Z)-gamma-bisabolene synthase
+4.2.3.41	Elisabethatriene synthase
+4.2.3.42	Aphidicolan-16-beta-ol synthase
+4.2.3.43	Fusicocca-2,10(14)-diene synthase
+4.2.3.44	Isopimara-7,15-diene synthase
+4.2.3.45	Phyllocladan-16-alpha-ol synthase
+4.2.3.46	Alpha-farnesene synthase
+4.2.3.47	Beta-farnesene synthase
+4.2.3.48	(3S,6E)-nerolidol synthase
+4.2.3.49	(3R,6E)-nerolidol synthase
+4.2.3.50	(+)-alpha-santalene synthase ((2Z,6Z)-farnesyl diphosphate cyclizing)
+4.2.3.51	Beta-phellandrene synthase (neryl-diphosphate-cyclizing)
+4.2.3.52	(4S)-beta-phellandrene synthase (geranyl-diphosphate-cyclizing)
+4.2.3.53	cyclizing)
+4.2.3.54	cyclizing)
+4.2.3.55	(S)-beta-bisabolene synthase
+4.2.3.56	Gamma-humulene synthase
+4.2.3.57	(-)-beta-caryophyllene synthase
+4.2.3.58	Longifolene synthase
+4.2.3.59	(E)-gamma-bisabolene synthase
+4.2.3.60	Germacrene C synthase
+4.2.3.61	5-epiaristolochene synthase
+4.2.3.62	(-)-gamma-cadinene synthase ((2Z,6E)-farnesyl diphosphate cyclizing)
+4.2.3.63	(+)-cubenene synthase
+4.2.3.64	(+)-epicubenol synthase
+4.2.3.65	Zingiberene synthase
+4.2.3.66	Beta-selinene cyclase
+4.2.3.67	Cis-muuroladiene synthase
+4.2.3.68	Beta-eudesmol synthase
+4.2.3.69	(+)-alpha-barbatene synthase
+4.2.3.70	Patchoulol synthase
+4.2.3.71	(E,E)-germacrene B synthase
+4.2.3.72	Alpha-gurjunene synthase
+4.2.3.73	Valencene synthase
+4.2.3.74	Presilphiperfolanol synthase
+4.2.3.75	(-)-germacrene D synthase
+4.2.3.76	(+)-delta-selinene synthase
+4.2.3.77	(+)-germacrene D synthase
+4.2.3.78	Beta-chamigrene synthase
+4.2.3.79	Thujopsene synthase
+4.2.3.80	Alpha-longipinene synthase
+4.2.3.81	Exo-alpha-bergamotene synthase
+4.2.3.82	Alpha-santalene synthase
+4.2.3.83	Beta-santalene synthase
+4.2.3.84	10-epi-gamma-eudesmol synthase
+4.2.3.85	Alpha-eudesmol synthase
+4.2.3.86	7-epi-alpha-selinene synthase
+4.2.3.87	Alpha-guaiene synthase
+4.2.3.88	Viridiflorene synthase
+4.2.3.89	(+)-beta-caryophyllene synthase
+4.2.3.90	5-epi-alpha-selinene synthase
+4.2.3.91	Cubebol synthase
+4.2.3.92	(+)-gamma-cadinene synthase
+4.2.3.93	Delta-guaiene synthase
+4.2.3.94	Gamma-curcumene synthase
+4.2.3.95	(-)-alpha-cuprenene synthase
+4.2.3.96	Avermitilol synthase
+4.2.3.97	(-)-delta-cadinene synthase
+4.2.3.98	(+)-T-muurolol synthase
+4.2.3.99	Labdatriene synthase
+4.2.3.100	Bicyclogermacrene synthase
+4.2.3.101	7-epi-sesquithujene synthase
+4.2.3.102	Sesquithujene synthase
+4.2.3.103	Ent-isokaurene synthase
+4.2.3.104	Alpha-humulene synthase
+4.2.3.105	Tricyclene synthase
+4.2.3.106	(E)-beta-ocimene synthase
+4.2.3.107	(+)-car-3-ene synthase
+4.2.3.108	1,8-cineole synthase
+4.2.3.109	(-)-sabinene synthase
+4.2.3.110	(+)-sabinene synthase
+4.2.3.111	(-)-alpha-terpineol synthase
+4.2.3.112	(+)-alpha-terpineol synthase
+4.2.3.113	Terpinolene synthase
+4.2.3.114	Gamma-terpinene synthase
+4.2.3.115	Alpha-terpinene synthase
+4.2.3.116	(+)-camphene synthase
+4.2.3.117	(-)-camphene synthase
+4.2.3.118	2-methylisoborneol synthase
+4.2.3.119	(-)-alpha-pinene synthase
+4.2.3.120	(-)-beta-pinene synthase
+4.2.3.121	(+)-alpha-pinene synthase
+4.2.3.122	(+)-beta-pinene synthase
+4.2.3.123	Beta-sesquiphellandrene synthase
+4.2.3.124	2-deoxy-scyllo-inosose synthase
+4.2.3.125	Alpha-muurolene synthase
+4.2.3.126	Gamma-muurolene synthase
+4.2.3.127	Beta-copaene synthase
+4.2.3.128	Beta-cubebene synthase
+4.2.3.129	(+)-sativene synthase
+4.2.3.130	Tetraprenyl-beta-curcumene synthase
+4.2.3.131	Miltiradiene synthase
+4.2.3.132	Neoabietadiene synthase
+4.2.3.133	Alpha-copaene synthase
+4.2.3.134	5-phosphonooxy-L-lysine phospho-lyase
+4.2.3.135	Delta(6)-protoilludene synthase
+4.2.3.136	Alpha-isocomene synthase
+4.2.3.137	(E)-2-epi-beta-caryophyllene synthase
+4.2.3.138	(+)-epi-alpha-bisabolol synthase
+4.2.3.139	Valerena-4,7(11)-diene synthase
+4.2.3.140	Cis-abienol synthase
+4.2.3.141	Sclareol synthase
+4.2.3.142	7-epizingiberene synthase ((2Z,6Z)-farnesyl diphosphate cyclizing)
+4.2.3.143	Kunzeaol synthase
+4.2.3.144	Geranyllinalool synthase
+4.2.3.145	Ophiobolin F synthase
+4.2.3.146	Cyclooctat-9-en-7-ol synthase
+4.2.3.147	Pimaradiene synthase
+4.2.3.148	Cembrene C synthase
+4.2.3.149	Nephthenol synthase
+4.2.3.150	Cembrene A synthase
+4.2.3.151	Pentamethylcyclopentadecatrienol synthase
+4.2.3.152	2-epi-5-epi-valiolone synthase
+4.2.3.153	(5-formylfuran-3-yl)methyl phosphate synthase
+4.2.99.1	Transferred entry: 4.2.2.1
+4.2.99.2	Transferred entry: 4.2.3.1
+4.2.99.3	Transferred entry: 4.2.2.2
+4.2.99.4	Transferred entry: 4.2.2.3
+4.2.99.5	Deleted entry
+4.2.99.6	Transferred entry: 4.2.2.5, 4.2.2.20 and 4.2.2.21
+4.2.99.7	Transferred entry: 4.2.3.2
+4.2.99.8	Transferred entry: 2.5.1.47
+4.2.99.9	Transferred entry: 2.5.1.48
+4.2.99.10	Transferred entry: 2.5.1.49
+4.2.99.11	Transferred entry: 4.2.3.3
+4.2.99.12	Carboxymethyloxysuccinate lyase
+4.2.99.13	Transferred entry: 2.5.1.50
+4.2.99.14	Transferred entry: 2.5.1.51
+4.2.99.15	Transferred entry: 2.5.1.52
+4.2.99.16	Transferred entry: 2.5.1.53
+4.2.99.17	Transferred entry: 2.5.1.51
+4.2.99.18	DNA-(apurinic or apyrimidinic site) lyase
+4.2.99.19	Transferred entry: 4.4.1.23
+4.2.99.20	2-succinyl-6-hydroxy-2,4-cyclohexadiene-1-carboxylate synthase
+4.2.99.21	Isochorismate lyase
+4.2.99.22	Tuliposide A-converting enzyme
+4.3.1.1	Aspartate ammonia-lyase
+4.3.1.2	Methylaspartate ammonia-lyase
+4.3.1.3	Histidine ammonia-lyase
+4.3.1.4	Formimidoyltetrahydrofolate cyclodeaminase
+4.3.1.5	Transferred entry: 4.3.1.23, 4.3.1.24 and 4.3.1.25
+4.3.1.6	Beta-alanyl-CoA ammonia-lyase
+4.3.1.7	Ethanolamine ammonia-lyase
+4.3.1.8	Transferred entry: 2.5.1.61
+4.3.1.9	Glucosaminate ammonia-lyase
+4.3.1.10	Serine-sulfate ammonia-lyase
+4.3.1.11	Deleted entry
+4.3.1.12	Ornithine cyclodeaminase
+4.3.1.13	Carbamoyl-serine ammonia-lyase
+4.3.1.14	3-aminobutyryl-CoA ammonia-lyase
+4.3.1.15	Diaminopropionate ammonia-lyase
+4.3.1.16	Threo-3-hydroxy-L-aspartate ammonia-lyase
+4.3.1.17	L-serine ammonia-lyase
+4.3.1.18	D-serine ammonia-lyase
+4.3.1.19	Threonine ammonia-lyase
+4.3.1.20	Erythro-3-hydroxy-L-aspartate ammonia-lyase
+4.3.1.21	Transferred entry: 4.3.1.9
+4.3.1.22	3,4-dihydroxyphenylalanine reductive deaminase
+4.3.1.23	Tyrosine ammonia-lyase
+4.3.1.24	Phenylalanine ammonia-lyase
+4.3.1.25	Phenylalanine/tyrosine ammonia-lyase
+4.3.1.26	Transferred entry: 1.21.3.9
+4.3.1.27	Threo-3-hydroxy-D-aspartate ammonia-lyase
+4.3.1.28	L-lysine cyclodeaminase
+4.3.1.29	D-glucosaminate-6-phosphate ammonia lyase
+4.3.1.30	dTDP-4-amino-4,6-dideoxy-D-glucose ammonia-lyase
+4.3.2.1	Argininosuccinate lyase
+4.3.2.2	Adenylosuccinate lyase
+4.3.2.3	Ureidoglycolate lyase
+4.3.2.4	Purine imidazole-ring cyclase
+4.3.2.5	Peptidylamidoglycolate lyase
+4.3.2.6	Gamma-L-glutamyl-butirosin B gamma-glutamyl cyclotransferase
+4.3.3.1	3-ketovalidoxylamine C-N-lyase
+4.3.3.2	Strictosidine synthase
+4.3.3.3	Deacetylisoipecoside synthase
+4.3.3.4	Deacetylipecoside synthase
+4.3.3.5	4'-demethylrebeccamycin synthase
+4.3.3.6	Pyridoxal 5'-phosphate synthase (glutamine hydrolyzing)
+4.3.3.7	4-hydroxy-tetrahydrodipicolinate synthase
+4.3.99.1	Transferred entry: 4.2.1.104
+4.3.99.2	Carboxybiotin decarboxylase
+4.3.99.3	7-carboxy-7-deazaguanine synthase
+4.3.99.4	Choline trimethylamine-lyase
+4.4.1.1	Cystathionine gamma-lyase
+4.4.1.2	Homocysteine desulfhydrase
+4.4.1.3	Dimethylpropiothetin dethiomethylase
+4.4.1.4	Alliin lyase
+4.4.1.5	Lactoylglutathione lyase
+4.4.1.6	S-alkylcysteine lyase
+4.4.1.7	Transferred entry: 2.5.1.18
+4.4.1.8	Cystathionine beta-lyase
+4.4.1.9	L-3-cyanoalanine synthase
+4.4.1.10	Cysteine lyase
+4.4.1.11	Methionine gamma-lyase
+4.4.1.12	Deleted entry
+4.4.1.13	Cysteine-S-conjugate beta-lyase
+4.4.1.14	1-aminocyclopropane-1-carboxylate synthase
+4.4.1.15	D-cysteine desulfhydrase
+4.4.1.16	Selenocysteine lyase
+4.4.1.17	Holocytochrome-c synthase
+4.4.1.18	Transferred entry: 1.8.3.5
+4.4.1.19	Phosphosulfolactate synthase
+4.4.1.20	Leukotriene-C(4) synthase
+4.4.1.21	S-ribosylhomocysteine lyase
+4.4.1.22	S-(hydroxymethyl)glutathione synthase
+4.4.1.23	2-hydroxypropyl-CoM lyase
+4.4.1.24	(2R)-sulfolactate sulfo-lyase
+4.4.1.25	L-cysteate sulfo-lyase
+4.4.1.26	Olivetolic acid cyclase
+4.4.1.27	Carbon disulfide lyase
+4.4.1.28	L-cysteine desulfidase
+4.4.1.29	Phycobiliprotein cysteine-84 phycobilin lyase
+4.4.1.30	Phycobiliprotein beta-cysteine-155 phycobilin lyase
+4.4.1.31	Phycoerythrocyanin alpha-cysteine-84 phycoviolobilin lyase/isomerase
+4.4.1.32	C-phycocyanin alpha-cysteine-84 phycocyanobilin lyase
+4.4.1.33	R-phycocyanin alpha-cysteine-84 phycourobilin lyase/isomerase
+4.5.1.1	DDT-dehydrochlorinase
+4.5.1.2	3-chloro-D-alanine dehydrochlorinase
+4.5.1.3	Dichloromethane dehalogenase
+4.5.1.4	L-2-amino-4-chloropent-4-enoate dehydrochlorinase
+4.5.1.5	S-carboxymethylcysteine synthase
+4.6.1.1	Adenylate cyclase
+4.6.1.2	Guanylate cyclase
+4.6.1.3	Transferred entry: 4.2.3.4
+4.6.1.4	Transferred entry: 4.2.3.5
+4.6.1.5	Transferred entry: 4.2.3.7
+4.6.1.6	Cytidylate cyclase
+4.6.1.7	Transferred entry: 4.2.3.8
+4.6.1.8	Transferred entry: 4.2.3.10
+4.6.1.9	Transferred entry: 4.2.3.11
+4.6.1.10	Transferred entry: 4.2.3.12
+4.6.1.11	Transferred entry: 4.2.3.13
+4.6.1.12	2-C-methyl-D-erythritol 2,4-cyclodiphosphate synthase
+4.6.1.13	Phosphatidylinositol diacylglycerol-lyase
+4.6.1.14	Glycosylphosphatidylinositol diacylglycerol-lyase
+4.6.1.15	FAD-AMP lyase (cyclizing)
+4.6.1.16	tRNA-intron lyase
+4.7.1.1	Alpha-D-ribose 1-methylphosphonate 5-phosphate C-P-lyase
+4.99.1.1	Protoporphyrin ferrochelatase
+4.99.1.2	Alkylmercury lyase
+4.99.1.3	Sirohydrochlorin cobaltochelatase
+4.99.1.4	Sirohydrochlorin ferrochelatase
+4.99.1.5	Aliphatic aldoxime dehydratase
+4.99.1.6	Indoleacetaldoxime dehydratase
+4.99.1.7	Phenylacetaldoxime dehydratase
+4.99.1.8	Heme ligase
+5.1.1.1	Alanine racemase
+5.1.1.2	Methionine racemase
+5.1.1.3	Glutamate racemase
+5.1.1.4	Proline racemase
+5.1.1.5	Lysine racemase
+5.1.1.6	Threonine racemase
+5.1.1.7	Diaminopimelate epimerase
+5.1.1.8	4-hydroxyproline epimerase
+5.1.1.9	Arginine racemase
+5.1.1.10	Amino-acid racemase
+5.1.1.11	Phenylalanine racemase (ATP-hydrolyzing)
+5.1.1.12	Ornithine racemase
+5.1.1.13	Aspartate racemase
+5.1.1.14	Nocardicin-A epimerase
+5.1.1.15	2-aminohexano-6-lactam racemase
+5.1.1.16	Protein-serine epimerase
+5.1.1.17	Isopenicillin-N epimerase
+5.1.1.18	Serine racemase
+5.1.1.19	O-ureido-serine racemase
+5.1.1.20	L-Ala-D/L-Glu epimerase
+5.1.1.21	Isoleucine 2-epimerase
+5.1.2.1	Lactate racemase
+5.1.2.2	Mandelate racemase
+5.1.2.3	3-hydroxybutyryl-CoA epimerase
+5.1.2.4	Acetoin racemase
+5.1.2.5	Tartrate epimerase
+5.1.2.6	Isocitrate epimerase
+5.1.3.1	Ribulose-phosphate 3-epimerase
+5.1.3.2	UDP-glucose 4-epimerase
+5.1.3.3	Aldose 1-epimerase
+5.1.3.4	L-ribulose-5-phosphate 4-epimerase
+5.1.3.5	UDP-arabinose 4-epimerase
+5.1.3.6	UDP-glucuronate 4-epimerase
+5.1.3.7	UDP-N-acetylglucosamine 4-epimerase
+5.1.3.8	N-acylglucosamine 2-epimerase
+5.1.3.9	N-acylglucosamine-6-phosphate 2-epimerase
+5.1.3.10	CDP-paratose 2-epimerase
+5.1.3.11	Cellobiose epimerase
+5.1.3.12	UDP-glucuronate 5'-epimerase
+5.1.3.13	dTDP-4-dehydrorhamnose 3,5-epimerase
+5.1.3.14	UDP-N-acetylglucosamine 2-epimerase (non-hydrolyzing)
+5.1.3.15	Glucose-6-phosphate 1-epimerase
+5.1.3.16	UDP-glucosamine 4-epimerase
+5.1.3.17	Heparosan-N-sulfate-glucuronate 5-epimerase
+5.1.3.18	GDP-mannose 3,5-epimerase
+5.1.3.19	Chondroitin-glucuronate 5-epimerase
+5.1.3.20	ADP-glyceromanno-heptose 6-epimerase
+5.1.3.21	Maltose epimerase
+5.1.3.22	L-ribulose-5-phosphate 3-epimerase
+5.1.3.23	UDP-2,3-diacetamido-2,3-dideoxyglucuronic acid 2-epimerase
+5.1.3.24	N-acetylneuraminate epimerase
+5.1.3.25	dTDP-L-rhamnose 4-epimerase
+5.1.3.26	4-epimerase
+5.1.3.27	dTDP-4-dehydro-6-deoxy-D-glucose 3-epimerase
+5.1.3.28	UDP-N-acetyl-L-fucosamine synthase
+5.1.3.29	L-fucose mutarotase
+5.1.3.30	D-psicose 3-epimerase
+5.1.3.31	D-tagatose 3-epimerase
+5.1.3.32	L-rhamnose mutarotase
+5.1.3.33	2-epi-5-epi-valiolone epimerase
+5.1.3.34	Monoglucosyldiacylglycerol epimerase
+5.1.3.35	2-epi-5-epi-valiolone 7-phosphate 2-epimerase
+5.1.3.36	Heparosan-glucuronate 5-epimerase
+5.1.3.37	Mannuronan 5-epimerase
+5.1.99.1	Methylmalonyl-CoA epimerase
+5.1.99.2	16-hydroxysteroid epimerase
+5.1.99.3	Allantoin racemase
+5.1.99.4	Alpha-methylacyl-CoA racemase
+5.1.99.5	Hydantoin racemase
+5.1.99.6	NAD(P)H-hydrate epimerase
+5.1.99.7	Dihydroneopterin triphosphate 2'-epimerase
+5.1.99.8	7,8-dihydroneopterin epimerase
+5.2.1.1	Maleate isomerase
+5.2.1.2	Maleylacetoacetate isomerase
+5.2.1.3	Deleted entry
+5.2.1.4	Maleylpyruvate isomerase
+5.2.1.5	Linoleate isomerase
+5.2.1.6	Furylfuramide isomerase
+5.2.1.7	Transferred entry: 3.1.1.64
+5.2.1.8	Peptidylprolyl isomerase
+5.2.1.9	Farnesol 2-isomerase
+5.2.1.10	2-chloro-4-carboxymethylenebut-2-en-1,4-olide isomerase
+5.2.1.11	Deleted entry
+5.2.1.12	Zeta-carotene isomerase
+5.2.1.13	Prolycopene isomerase
+5.2.1.14	Beta-carotene isomerase
+5.3.1.1	Triose-phosphate isomerase
+5.3.1.2	Deleted entry
+5.3.1.3	D-arabinose isomerase
+5.3.1.4	L-arabinose isomerase
+5.3.1.5	Xylose isomerase
+5.3.1.6	Ribose-5-phosphate isomerase
+5.3.1.7	Mannose isomerase
+5.3.1.8	Mannose-6-phosphate isomerase
+5.3.1.9	Glucose-6-phosphate isomerase
+5.3.1.10	Transferred entry: 3.5.99.6
+5.3.1.11	Deleted entry
+5.3.1.12	Glucuronate isomerase
+5.3.1.13	Arabinose-5-phosphate isomerase
+5.3.1.14	L-rhamnose isomerase
+5.3.1.15	D-lyxose ketol-isomerase
+5.3.1.16	isomerase
+5.3.1.17	5-dehydro-4-deoxy-D-glucuronate isomerase
+5.3.1.18	Deleted entry
+5.3.1.19	Transferred entry: 2.6.1.16
+5.3.1.20	Ribose isomerase
+5.3.1.21	Corticosteroid side-chain-isomerase
+5.3.1.22	Hydroxypyruvate isomerase
+5.3.1.23	S-methyl-5-thioribose-1-phosphate isomerase
+5.3.1.24	Phosphoribosylanthranilate isomerase
+5.3.1.25	L-fucose isomerase
+5.3.1.26	Galactose-6-phosphate isomerase
+5.3.1.27	6-phospho-3-hexuloisomerase
+5.3.1.28	D-sedoheptulose 7-phosphate isomerase
+5.3.1.29	Ribose 1,5-bisphosphate isomerase
+5.3.1.30	5-deoxy-glucuronate isomerase
+5.3.1.31	Sulfoquinovose isomerase
+5.3.1.32	(4S)-4-hydroxy-5-phosphonooxypentane-2,3-dione isomerase
+5.3.2.1	Phenylpyruvate tautomerase
+5.3.2.2	Oxaloacetate tautomerase
+5.3.2.3	deoxy-alpha-D-galactopyranose-forming)
+5.3.2.4	deoxy-alpha-D-glucopyranose-forming)
+5.3.2.5	2,3-diketo-5-methylthiopentyl-1-phosphate enolase
+5.3.2.6	2-hydroxymuconate tautomerase
+5.3.2.7	Ascopyrone tautomerase
+5.3.2.8	4-oxalomesaconate tautomerase
+5.3.3.1	Steroid Delta-isomerase
+5.3.3.2	Isopentenyl-diphosphate Delta-isomerase
+5.3.3.3	Vinylacetyl-CoA Delta-isomerase
+5.3.3.4	Muconolactone Delta-isomerase
+5.3.3.5	Cholestenol Delta-isomerase
+5.3.3.6	Methylitaconate Delta-isomerase
+5.3.3.7	Aconitate Delta-isomerase
+5.3.3.8	Dodecenoyl-CoA isomerase
+5.3.3.9	Prostaglandin-A(1) Delta-isomerase
+5.3.3.10	5-carboxymethyl-2-hydroxymuconate Delta-isomerase
+5.3.3.11	Isopiperitenone Delta-isomerase
+5.3.3.12	L-dopachrome isomerase
+5.3.3.13	Polyenoic fatty acid isomerase
+5.3.3.14	Trans-2-decenoyl-[acyl-carrier-protein] isomerase
+5.3.3.15	Transferred entry: 5.3.2.7
+5.3.3.16	Transferred entry: 5.3.2.8
+5.3.3.17	Trans-2,3-dihydro-3-hydroxyanthranilate isomerase
+5.3.3.18	2-(1,2-epoxy-1,2-dihydrophenyl)acetyl-CoA isomerase
+5.3.3.19	3-((4R)-4-hydroxycyclohexa-1,5-dien-1-yl)-2-oxopropanoate isomerase
+5.3.4.1	Protein disulfide-isomerase
+5.3.99.1	Deleted entry
+5.3.99.2	Prostaglandin-D synthase
+5.3.99.3	Prostaglandin-E synthase
+5.3.99.4	Prostaglandin-I synthase
+5.3.99.5	Thromboxane-A synthase
+5.3.99.6	Allene-oxide cyclase
+5.3.99.7	Styrene-oxide isomerase
+5.3.99.8	Capsanthin/capsorubin synthase
+5.3.99.9	Neoxanthin synthase
+5.3.99.10	Thiazole tautomerase
+5.3.99.11	2-keto-myo-inositol isomerase
+5.4.1.1	Lysolecithin acylmutase
+5.4.1.2	Transferred entry: 5.4.99.61
+5.4.1.3	2-methylfumaryl-CoA isomerase
+5.4.1.4	D-galactarolactone isomerase
+5.4.2.1	Transferred entry: 5.4.2.11 and 5.4.2.12
+5.4.2.2	Phosphoglucomutase (alpha-D-glucose-1,6-bisphosphate-dependent)
+5.4.2.3	Phosphoacetylglucosamine mutase
+5.4.2.4	Bisphosphoglycerate mutase
+5.4.2.5	Phosphoglucomutase (glucose-cofactor)
+5.4.2.6	Beta-phosphoglucomutase
+5.4.2.7	Phosphopentomutase
+5.4.2.8	Phosphomannomutase
+5.4.2.9	Phosphoenolpyruvate mutase
+5.4.2.10	Phosphoglucosamine mutase
+5.4.2.11	Phosphoglycerate mutase (2,3-diphosphoglycerate-dependent)
+5.4.2.12	Phosphoglycerate mutase (2,3-diphosphoglycerate-independent)
+5.4.3.1	Deleted entry
+5.4.3.2	Lysine 2,3-aminomutase
+5.4.3.3	Beta-lysine 5,6-aminomutase
+5.4.3.4	D-lysine 5,6-aminomutase
+5.4.3.5	D-ornithine 4,5-aminomutase
+5.4.3.6	Tyrosine 2,3-aminomutase
+5.4.3.7	Leucine 2,3-aminomutase
+5.4.3.8	Glutamate-1-semialdehyde 2,1-aminomutase
+5.4.3.9	Glutamate 2,3-aminomutase
+5.4.3.10	Phenylalanine aminomutase (L-beta-phenylalanine forming)
+5.4.3.11	Phenylalanine aminomutase (D-beta-phenylalanine forming)
+5.4.4.1	(Hydroxyamino)benzene mutase
+5.4.4.2	Isochorismate synthase
+5.4.4.3	3-(hydroxyamino)phenol mutase
+5.4.4.4	Geraniol isomerase
+5.4.4.5	9,12-octadecadienoate 8-hydroperoxide 8R-isomerase
+5.4.4.6	9,12-octadecadienoate 8-hydroperoxide 8S-isomerase
+5.4.4.7	Hydroperoxy icosatetraenoate isomerase
+5.4.99.1	Methylaspartate mutase
+5.4.99.2	Methylmalonyl-CoA mutase
+5.4.99.3	2-acetolactate mutase
+5.4.99.4	2-methyleneglutarate mutase
+5.4.99.5	Chorismate mutase
+5.4.99.6	Transferred entry: 5.4.4.2
+5.4.99.7	Lanosterol synthase
+5.4.99.8	Cycloartenol synthase
+5.4.99.9	UDP-galactopyranose mutase
+5.4.99.10	Transferred entry: 5.4.99.11
+5.4.99.11	Isomaltulose synthase
+5.4.99.12	tRNA pseudouridine(38-40) synthase
+5.4.99.13	Isobutyryl-CoA mutase
+5.4.99.14	4-carboxymethyl-4-methylbutenolide mutase
+5.4.99.15	(1->4)-alpha-D-glucan 1-alpha-D-glucosylmutase
+5.4.99.16	Maltose alpha-D-glucosyltransferase
+5.4.99.17	Squalene--hopene cyclase
+5.4.99.18	5-(carboxyamino)imidazole ribonucleotide mutase
+5.4.99.19	16S rRNA pseudouridine(516) synthase
+5.4.99.20	23S rRNA pseudouridine(2457) synthase
+5.4.99.21	23S rRNA pseudouridine(2604) synthase
+5.4.99.22	23S rRNA pseudouridine(2605) synthase
+5.4.99.23	23S rRNA pseudouridine(1911/1915/1917) synthase
+5.4.99.24	23S rRNA pseudouridine(955/2504/2580) synthase
+5.4.99.25	tRNA pseudouridine(55) synthase
+5.4.99.26	tRNA pseudouridine(65) synthase
+5.4.99.27	tRNA pseudouridine(13) synthase
+5.4.99.28	tRNA pseudouridine(32) synthase
+5.4.99.29	23S rRNA pseudouridine(746) synthase
+5.4.99.30	UDP-arabinopyranose mutase
+5.4.99.31	Thalianol synthase
+5.4.99.32	Protostadienol synthase
+5.4.99.33	Cucurbitadienol synthase
+5.4.99.34	Germanicol synthase
+5.4.99.35	Taraxerol synthase
+5.4.99.36	Isomultiflorenol synthase
+5.4.99.37	Dammaradiene synthase
+5.4.99.38	Camelliol C synthase
+5.4.99.39	Beta-amyrin synthase
+5.4.99.40	Alpha-amyrin synthase
+5.4.99.41	Lupeol synthase
+5.4.99.42	tRNA pseudouridine(31) synthase
+5.4.99.43	21S rRNA pseudouridine(2819) synthase
+5.4.99.44	Mitochondrial tRNA pseudouridine(27/28) synthase
+5.4.99.45	tRNA pseudouridine(38/39) synthase
+5.4.99.46	Shionone synthase
+5.4.99.47	Parkeol synthase
+5.4.99.48	Achilleol B synthase
+5.4.99.49	Glutinol synthase
+5.4.99.50	Friedelin synthase
+5.4.99.51	Baccharis oxide synthase
+5.4.99.52	Alpha-seco-amyrin synthase
+5.4.99.53	Marneral synthase
+5.4.99.54	Beta-seco-amyrin synthase
+5.4.99.55	Delta-amyrin synthase
+5.4.99.56	Tirucalladienol synthase
+5.4.99.57	Baruol synthase
+5.4.99.58	Methylornithine synthase
+5.4.99.59	dTDP-fucopyranose mutase
+5.4.99.60	Cobalt-precorrin-8 methylmutase
+5.4.99.61	Precorrin-8X methylmutase
+5.4.99.62	D-ribose pyranase
+5.4.99.63	Ethylmalonyl-CoA mutase
+5.5.1.1	Muconate cycloisomerase
+5.5.1.2	3-carboxy-cis,cis-muconate cycloisomerase
+5.5.1.3	Tetrahydroxypteridine cycloisomerase
+5.5.1.4	Inositol-3-phosphate synthase
+5.5.1.5	Carboxy-cis,cis-muconate cyclase
+5.5.1.6	Chalcone isomerase
+5.5.1.7	Chloromuconate cycloisomerase
+5.5.1.8	(+)-bornyl diphosphate synthase
+5.5.1.9	Cycloeucalenol cycloisomerase
+5.5.1.10	Alpha-pinene-oxide decyclase
+5.5.1.11	Dichloromuconate cycloisomerase
+5.5.1.12	Copalyl diphosphate synthase
+5.5.1.13	Ent-copalyl diphosphate synthase
+5.5.1.14	Syn-copalyl-diphosphate synthase
+5.5.1.15	Terpentedienyl-diphosphate synthase
+5.5.1.16	Halimadienyl-diphosphate synthase
+5.5.1.17	(S)-beta-macrocarpene synthase
+5.5.1.18	Lycopene epsilon-cyclase
+5.5.1.19	Lycopene beta-cyclase
+5.5.1.20	Prosolanapyrone-III cycloisomerase
+5.5.1.21	Transferred entry: 4.2.1.133
+5.5.1.22	(-)-bornyl diphosphate synthase
+5.5.1.23	Aklanonic acid methyl ester cyclase
+5.5.1.24	Tocopherol cyclase
+5.5.1.25	3,6-anhydro-L-galactonate cycloisomerase
+5.5.1.26	Nogalonic acid methyl ester cyclase
+5.5.1.27	D-galactarolactone cycloisomerase
+5.99.1.1	Thiocyanate isomerase
+5.99.1.2	DNA topoisomerase
+5.99.1.3	DNA topoisomerase (ATP-hydrolyzing)
+5.99.1.4	2-hydroxychromene-2-carboxylate isomerase
+6.1.1.1	Tyrosine--tRNA ligase
+6.1.1.2	Tryptophan--tRNA ligase
+6.1.1.3	Threonine--tRNA ligase
+6.1.1.4	Leucine--tRNA ligase
+6.1.1.5	Isoleucine--tRNA ligase
+6.1.1.6	Lysine--tRNA ligase
+6.1.1.7	Alanine--tRNA ligase
+6.1.1.8	Deleted entry
+6.1.1.9	Valine--tRNA ligase
+6.1.1.10	Methionine--tRNA ligase
+6.1.1.11	Serine--tRNA ligase
+6.1.1.12	Aspartate--tRNA ligase
+6.1.1.13	D-alanine--poly(phosphoribitol) ligase
+6.1.1.14	Glycine--tRNA ligase
+6.1.1.15	Proline--tRNA ligase
+6.1.1.16	Cysteine--tRNA ligase
+6.1.1.17	Glutamate--tRNA ligase
+6.1.1.18	Glutamine--tRNA ligase
+6.1.1.19	Arginine--tRNA ligase
+6.1.1.20	Phenylalanine--tRNA ligase
+6.1.1.21	Histidine--tRNA ligase
+6.1.1.22	Asparagine--tRNA ligase
+6.1.1.23	Aspartate--tRNA(Asn) ligase
+6.1.1.24	Glutamate--tRNA(Gln) ligase
+6.1.1.25	Deleted entry
+6.1.1.26	Pyrrolysine--tRNA(Pyl) ligase
+6.1.1.27	O-phosphoserine--tRNA ligase
+6.1.1.28	Deleted entry
+6.1.2.1	D-alanine--(R)-lactate ligase
+6.1.2.2	Nebramycin 5' synthase
+6.2.1.1	Acetate--CoA ligase
+6.2.1.2	Butyrate--CoA ligase
+6.2.1.3	Long-chain-fatty-acid--CoA ligase
+6.2.1.4	Succinate--CoA ligase (GDP-forming)
+6.2.1.5	Succinate--CoA ligase (ADP-forming)
+6.2.1.6	Glutarate--CoA ligase
+6.2.1.7	Cholate--CoA ligase
+6.2.1.8	Oxalate--CoA ligase
+6.2.1.9	Malate--CoA ligase
+6.2.1.10	Acid--CoA ligase (GDP-forming)
+6.2.1.11	Biotin--CoA ligase
+6.2.1.12	4-coumarate--CoA ligase
+6.2.1.13	Acetate--CoA ligase (ADP-forming)
+6.2.1.14	6-carboxyhexanoate--CoA ligase
+6.2.1.15	Arachidonate--CoA ligase
+6.2.1.16	Acetoacetate--CoA ligase
+6.2.1.17	Propionate--CoA ligase
+6.2.1.18	Citrate--CoA ligase
+6.2.1.19	Long-chain-fatty-acid--luciferin-component ligase
+6.2.1.20	Long-chain-fatty-acid--[acyl-carrier-protein] ligase
+6.2.1.21	Transferred entry: 6.2.1.30
+6.2.1.22	[Citrate (pro-3S)-lyase] ligase
+6.2.1.23	Dicarboxylate--CoA ligase
+6.2.1.24	Phytanate--CoA ligase
+6.2.1.25	Benzoate--CoA ligase
+6.2.1.26	o-succinylbenzoate--CoA ligase
+6.2.1.27	4-hydroxybenzoate--CoA ligase
+6.2.1.28	3-alpha,7-alpha-dihydroxy-5-beta-cholestanate--CoA ligase
+6.2.1.29	Transferred entry: 6.2.1.7
+6.2.1.30	Phenylacetate--CoA ligase
+6.2.1.31	2-furoate--CoA ligase
+6.2.1.32	Anthranilate--CoA ligase
+6.2.1.33	4-chlorobenzoate--CoA ligase
+6.2.1.34	Trans-feruloyl-CoA synthase
+6.2.1.35	ACP-SH:acetate ligase
+6.2.1.36	3-hydroxypropionyl-CoA synthase
+6.2.1.37	3-hydroxybenzoate--CoA ligase
+6.2.1.38	(2,2,3-trimethyl-5-oxocyclopent-3-enyl)acetyl-CoA synthase
+6.2.1.39	[Butirosin acyl-carrier protein]--L-glutamate ligase
+6.2.1.40	4-hydroxybutyrate--CoA ligase
+6.2.1.41	-CoA ligase
+6.2.1.42	3-oxocholest-4-en-26-oate--CoA ligase
+6.2.1.43	2-hydroxy-7-methoxy-5-methyl-1-naphthoate--CoA ligase
+6.2.1.44	3-(methylthio)propionyl--CoA ligase
+6.2.1.45	E1 ubiquitin-activating enzyme
+6.2.1.46	L-allo-isoleucine:holo-[CmaA peptidyl-carrier protein] ligase
+6.3.1.1	Aspartate--ammonia ligase
+6.3.1.2	Glutamate--ammonia ligase
+6.3.1.3	Transferred entry: 6.3.4.13
+6.3.1.4	Aspartate--ammonia ligase (ADP-forming)
+6.3.1.5	NAD(+) synthase
+6.3.1.6	Glutamate--ethylamine ligase
+6.3.1.7	4-methyleneglutamate--ammonia ligase
+6.3.1.8	Glutathionylspermidine synthase
+6.3.1.9	Trypanothione synthase
+6.3.1.10	Adenosylcobinamide-phosphate synthase
+6.3.1.11	Glutamate--putrescine ligase
+6.3.1.12	D-aspartate ligase
+6.3.1.13	ligase
+6.3.1.14	Diphthine--ammonia ligase
+6.3.1.15	8-demethylnovobiocic acid synthase
+6.3.1.16	Transferred entry: 6.3.3.6
+6.3.1.17	Beta-citrylglutamate synthase
+6.3.1.18	Gamma-glutamylanilide synthase
+6.3.1.19	Prokaryotic ubiquitin-like protein ligase
+6.3.2.1	Pantoate--beta-alanine ligase (AMP-forming)
+6.3.2.2	Glutamate--cysteine ligase
+6.3.2.3	Glutathione synthase
+6.3.2.4	D-alanine--D-alanine ligase
+6.3.2.5	Phosphopantothenate--cysteine ligase
+6.3.2.6	Phosphoribosylaminoimidazolesuccinocarboxamide synthase
+6.3.2.7	UDP-N-acetylmuramoyl-L-alanyl-D-glutamate--L-lysine ligase
+6.3.2.8	UDP-N-acetylmuramate--L-alanine ligase
+6.3.2.9	UDP-N-acetylmuramoyl-L-alanine--D-glutamate ligase
+6.3.2.10	UDP-N-acetylmuramoyl-tripeptide--D-alanyl-D-alanine ligase
+6.3.2.11	Carnosine synthase
+6.3.2.12	Dihydrofolate synthase
+6.3.2.13	UDP-N-acetylmuramoyl-L-alanyl-D-glutamate--2,6-diaminopimelate ligase
+6.3.2.14	Enterobactin synthase
+6.3.2.15	Transferred entry: 6.3.2.10
+6.3.2.16	D-alanine--alanyl-poly(glycerolphosphate) ligase
+6.3.2.17	Tetrahydrofolate synthase
+6.3.2.18	Gamma-glutamylhistamine synthase
+6.3.2.19	Transferred entry: 2.3.2.23, 2.3.2.27 and 6.2.1.45
+6.3.2.20	Indoleacetate--lysine synthetase
+6.3.2.21	Ubiquitin--calmodulin ligase
+6.3.2.22	Transferred entry: 6.3.1.14
+6.3.2.23	Homoglutathione synthase
+6.3.2.24	Tyrosine--arginine ligase
+6.3.2.25	Tubulin--tyrosine ligase
+6.3.2.26	N-(5-amino-5-carboxypentanoyl)-L-cysteinyl-D-valine synthase
+6.3.2.27	Transferred entry: 6.3.2.38 and 6.3.2.39
+6.3.2.28	Transferred entry: 6.3.2.49
+6.3.2.29	Cyanophycin synthase (L-aspartate-adding)
+6.3.2.30	Cyanophycin synthase (L-arginine-adding)
+6.3.2.31	Coenzyme F420-0:L-glutamate ligase
+6.3.2.32	Coenzyme gamma-F420-2:alpha-L-glutamate ligase
+6.3.2.33	Tetrahydrosarcinapterin synthase
+6.3.2.34	Coenzyme F420-1:gamma-L-glutamate ligase
+6.3.2.35	D-alanine--D-serine ligase
+6.3.2.36	4-phosphopantoate--beta-alanine ligase
+6.3.2.37	UDP-N-acetylmuramoyl-L-alanyl-D-glutamate--D-lysine ligase
+6.3.2.38	N(2)-citryl-N(6)-acetyl-N(6)-hydroxylysine synthase
+6.3.2.39	Aerobactin synthase
+6.3.2.40	Cyclopeptine synthase
+6.3.2.41	N-acetylaspartylglutamate synthase
+6.3.2.42	N-acetylaspartylglutamylglutamate synthase
+6.3.2.43	[Lysine-biosynthesis-protein LysW]--L-2-aminoadipate ligase
+6.3.2.44	Pantoate--beta-alanine ligase (ADP-forming)
+6.3.2.45	diaminoheptanedioate ligase
+6.3.2.46	Fumarate--(S)-2,3-diaminopropanoate ligase
+6.3.2.47	Dapdiamide A synthase
+6.3.2.48	L-arginine-specific L-amino acid ligase
+6.3.2.49	L-alanine--L-anticapsin ligase
+6.3.3.1	Phosphoribosylformylglycinamidine cyclo-ligase
+6.3.3.2	5-formyltetrahydrofolate cyclo-ligase
+6.3.3.3	Dethiobiotin synthase
+6.3.3.4	(Carboxyethyl)arginine beta-lactam-synthase
+6.3.3.5	O-ureido-D-serine cyclo-ligase
+6.3.3.6	Carbapenam-3-carboxylate synthase
+6.3.4.1	Transferred entry: 6.3.5.2
+6.3.4.2	CTP synthase (glutamine hydrolyzing)
+6.3.4.3	Formate--tetrahydrofolate ligase
+6.3.4.4	Adenylosuccinate synthase
+6.3.4.5	Argininosuccinate synthase
+6.3.4.6	Urea carboxylase
+6.3.4.7	Ribose-5-phosphate--ammonia ligase
+6.3.4.8	Imidazoleacetate--phosphoribosyldiphosphate ligase
+6.3.4.9	Biotin--[methylmalonyl-CoA-carboxytransferase] ligase
+6.3.4.10	Biotin--[propionyl-CoA-carboxylase (ATP-hydrolyzing)] ligase
+6.3.4.11	Biotin--[methylcrotonoyl-CoA-carboxylase] ligase
+6.3.4.12	Glutamate--methylamine ligase
+6.3.4.13	Phosphoribosylamine--glycine ligase
+6.3.4.14	Biotin carboxylase
+6.3.4.15	Biotin--[acetyl-CoA-carboxylase] ligase
+6.3.4.16	Carbamoyl-phosphate synthase (ammonia)
+6.3.4.17	Formate--dihydrofolate ligase
+6.3.4.18	5-(carboxyamino)imidazole ribonucleotide synthase
+6.3.4.19	tRNA(Ile)-lysidine synthetase
+6.3.4.20	7-cyano-7-deazaguanine synthase
+6.3.4.21	Nicotinate phosphoribosyltransferase
+6.3.4.22	tRNA(Ile)(2)-agmatinylcytidine synthase
+6.3.4.23	Formate--phosphoribosylaminoimidazolecarboxamide ligase
+6.3.4.24	Tyramine--L-glutamate ligase
+6.3.5.1	NAD(+) synthase (glutamine-hydrolyzing)
+6.3.5.2	GMP synthase (glutamine-hydrolyzing)
+6.3.5.3	Phosphoribosylformylglycinamidine synthase
+6.3.5.4	Asparagine synthase (glutamine-hydrolyzing)
+6.3.5.5	Carbamoyl-phosphate synthase (glutamine-hydrolyzing)
+6.3.5.6	Asparaginyl-tRNA synthase (glutamine-hydrolyzing)
+6.3.5.7	Glutaminyl-tRNA synthase (glutamine-hydrolyzing)
+6.3.5.8	Transferred entry: 2.6.1.85
+6.3.5.9	Hydrogenobyrinic acid a,c-diamide synthase (glutamine-hydrolyzing)
+6.3.5.10	Adenosylcobyric acid synthase (glutamine-hydrolyzing)
+6.3.5.11	Cobyrinate a,c-diamide synthase (glutamine-hydrolyzing)
+6.4.1.1	Pyruvate carboxylase
+6.4.1.2	Acetyl-CoA carboxylase
+6.4.1.3	Propionyl-CoA carboxylase
+6.4.1.4	Methylcrotonoyl-CoA carboxylase
+6.4.1.5	Geranoyl-CoA carboxylase
+6.4.1.6	Acetone carboxylase
+6.4.1.7	2-oxoglutarate carboxylase
+6.4.1.8	Acetophenone carboxylase
+6.5.1.1	DNA ligase (ATP)
+6.5.1.2	DNA ligase (NAD(+))
+6.5.1.3	RNA ligase (ATP)
+6.5.1.4	RNA 3'-terminal-phosphate cyclase (ATP)
+6.5.1.5	RNA 3'-terminal-phosphate cyclase (GTP)
+6.5.1.6	DNA ligase (ATP or NAD(+))
+6.5.1.7	DNA ligase (ATP, ADP or GTP)
+6.6.1.1	Magnesium chelatase
+6.6.1.2	Cobaltochelatase
diff --git a/KronaTools/deployResources.sh b/KronaTools/deployResources.sh
new file mode 100755
index 0000000..bed8757
--- /dev/null
+++ b/KronaTools/deployResources.sh
@@ -0,0 +1,43 @@
+#! /bin/bash
+
+if [ $# -lt 1 ]
+then
+	echo ""
+	echo "deployResources.sh <target>"
+	echo ""
+	echo "Links Krona web resources to <target> (i.e. a folder within /var/www) to create"
+	echo "a local server. Krona charts can then be made to point to these resources when"
+	echo "they are created (see -u). This is useful for deployment on isolated intranets."
+	echo ""
+	
+	exit
+fi
+
+target=$1
+
+if [ ! -e $target ]
+then
+	echo "$target does not exist...attempting to create..."
+	mkdir $target
+	
+	if [ $? != "0" ]
+	then
+		echo "ERROR: could not create $target."
+		exit
+	fi
+fi
+
+if [ ! -e $target/src ]
+then
+	mkdir $target/src
+fi
+
+if [ ! -e $target/img ]
+then
+	mkdir $target/img
+fi
+
+cp $PWD/src/krona-*.js $target/src
+cp $PWD/img/hidden.png $PWD/img/favicon.ico $PWD/img/loading.gif $PWD/img/logo-med.png $target/img
+
+echo "Finished."
diff --git a/KronaTools/img/favicon.ico b/KronaTools/img/favicon.ico
new file mode 100644
index 0000000..1ff0d01
Binary files /dev/null and b/KronaTools/img/favicon.ico differ
diff --git a/KronaTools/img/favicon.uri b/KronaTools/img/favicon.uri
new file mode 100644
index 0000000..49402ab
--- /dev/null
+++ b/KronaTools/img/favicon.uri
@@ -0,0 +1 @@
+data:image/x-icon;base64,AAABAAMAEBAAAAEAIABoBAAANgAAABgYAAABACAAiAkAAJ4EAAAgIAAAAQAgAKgQAAAmDgAAKAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wCAgIAC////AP///wC0tKJHlZWSqI6OmuRxcXn9koaK9J2Ym8uNm5V73PPoFv///wAAAAAD////AP///wCAgIAC////AP//7xCHh4OodHSi/2xqw/9nZ9H/XVuU/9eFqv/njb7/yYiq/5GAiOifqKJV////AAAAAAL///8A////AO3t2w56eoHPdHLH/3Vz3vx4dtz7dXTb/mVimv/XhKn/8ZPG/fSVx/vvlcT/kG+E/32Himb///8AAAAAA////wB0dHageHbO/3585fl5d9r/dnTX/3V02/5mYpz80X2i/eaIuv/ukcD/wXak/I6Maf+OkXD9iIKjL////wC [...]
\ No newline at end of file
diff --git a/KronaTools/img/hidden.png b/KronaTools/img/hidden.png
new file mode 100644
index 0000000..0f9ef30
Binary files /dev/null and b/KronaTools/img/hidden.png differ
diff --git a/KronaTools/img/hidden.uri b/KronaTools/img/hidden.uri
new file mode 100644
index 0000000..e7790be
--- /dev/null
+++ b/KronaTools/img/hidden.uri
@@ -0,0 +1 @@
+data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oLCBQhNQwWVnsAAAAidEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOHqHdDAAABE0lEQVQYGQEIAff+AwAAABkAAAAAAAAA+gAAAAAAAAAAAAAAAAAAAAAAAAAMAwAAAAAAAAANAAAAAAAAAPoAAAAAAAAADAAAAAYAAAD0AwAAAPoAAAAAAAAAAAAAAPoAAAAMAAAADQAAAPoAAAD6AAAAAAAAAAAAAAAAAAAAAAwAAAAZAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAABkAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAGQAAAAwAAAAAAA [...]
\ No newline at end of file
diff --git a/KronaTools/img/loading.uri b/KronaTools/img/loading.uri
new file mode 100644
index 0000000..abeddbb
--- /dev/null
+++ b/KronaTools/img/loading.uri
@@ -0,0 +1 @@
+data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHB [...]
\ No newline at end of file
diff --git a/KronaTools/img/logo-med.png b/KronaTools/img/logo-med.png
new file mode 100644
index 0000000..406a6dc
Binary files /dev/null and b/KronaTools/img/logo-med.png differ
diff --git a/KronaTools/img/logo-med.uri b/KronaTools/img/logo-med.uri
new file mode 100644
index 0000000..104a14c
--- /dev/null
+++ b/KronaTools/img/logo-med.uri
@@ -0,0 +1 @@
+data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANgAAAA8CAYAAAAE9XR5AAAC0WlDQ1BJQ0MgUHJvZmlsZQAAOI2NlM9LFGEYx7+zjRgoQWBme4ihQ0ioTBZlROWuv9i0bVl/lBLE7Oy7u5Ozs9PM7JoiEV46ZtE9Kg8e+gM8eOiUl8LALALpblFEgpeS7Xlnxt0R7ccLM/N5nx/f53nf4X2BGlkxTT0kAXnDsZJ9Uen66JhU+xEhHEEdwqhTVNuMJBIDoMFjsWtsvofAvyute/v/OurStpoHhP1A6Eea2Sqw7xfZC1lqBBC5XsOEYzrE9zhbnv0x55TH8659KNlFvEh8QDUtHv+auEPNKWmgRiRuyQZiUgHO60XV7+cgPfXMGB6k73Hq6S6ze3wWZtJKdz9xG/HnNOvu4ZrE8xmtN0bcTM9axuod9lg4oTmxIY9DI4YeH/C5yUjFr/qaoulEk9v6dmmwZ9t+S7 [...]
\ No newline at end of file
diff --git a/KronaTools/img/logo-small.png b/KronaTools/img/logo-small.png
new file mode 100644
index 0000000..a62ee73
Binary files /dev/null and b/KronaTools/img/logo-small.png differ
diff --git a/KronaTools/img/logo-small.uri b/KronaTools/img/logo-small.uri
new file mode 100644
index 0000000..62547b5
--- /dev/null
+++ b/KronaTools/img/logo-small.uri
@@ -0,0 +1 @@
+data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGwAAAAeCAYAAADJjPsHAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY2 [...]
\ No newline at end of file
diff --git a/KronaTools/img/logo.png b/KronaTools/img/logo.png
new file mode 100644
index 0000000..6d18d56
Binary files /dev/null and b/KronaTools/img/logo.png differ
diff --git a/KronaTools/img/logo.uri b/KronaTools/img/logo.uri
new file mode 100644
index 0000000..e245d44
--- /dev/null
+++ b/KronaTools/img/logo.uri
@@ -0,0 +1 @@
+data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAKRGlDQ1BJQ0MgUHJvZmlsZQAAeAGdlndUFNcXx9/MbC+0XZYiZem9twWkLr1IlSYKy+4CS1nWZRewN0QFIoqICFYkKGLAaCgSK6JYCAgW7AEJIkoMRhEVlczGHPX3Oyf5/U7eH3c+8333nnfn3vvOGQAoASECYQ6sAEC2UCKO9PdmxsUnMPG9AAZEgAM2AHC4uaLQKL9ogK5AXzYzF3WS8V8LAuD1LYBaAK5bBIQzmX/p/+9DkSsSSwCAwtEAOx4/l4tyIcpZ+RKRTJ9EmZ6SKWMYI2MxmiDKqjJO+8Tmf/p8Yk8Z87KFPNRHlrOIl82TcRfKG/OkfJSREJSL8gT8fJRvoKyfJc0WoPwGZXo2n5MLAIYi0yV8bjrK1ihTxNGRbJTnAkCgpH3FKV+xhF+A5gkAO0e0RCxIS5cwjb [...]
\ No newline at end of file
diff --git a/KronaTools/install.pl b/KronaTools/install.pl
new file mode 100755
index 0000000..d461265
--- /dev/null
+++ b/KronaTools/install.pl
@@ -0,0 +1,132 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+use strict;
+
+use Cwd 'abs_path';
+use Getopt::Long;
+
+my $path = '/usr/local';
+my $taxonomyDir;
+my $help;
+
+GetOptions(
+	'prefix=s'   => \$path,
+	'taxonomy=s' => \$taxonomyDir,
+	'help' => \$help
+	);
+
+if ( $help )
+{
+	print "./install.pl [-prefix /path/to/install] [-taxonomy /path/to/taxonomy]\n";
+	exit;
+}
+
+$path = abs_path($path);
+
+if ( defined $taxonomyDir )
+{
+	$taxonomyDir = abs_path($taxonomyDir);
+}
+
+my $scriptPath = abs_path('scripts');
+
+createDir($path);
+createDir("$path/bin");
+
+print "Creating links...\n";
+
+foreach my $script
+(qw(
+	ClassifyBLAST
+	GetContigMagnitudes
+	GetLCA
+	GetLibPath
+	GetTaxIDFromAcc
+	GetTaxInfo
+	ImportBLAST
+	ImportDiskUsage
+	ImportEC
+	ImportFCP
+	ImportGalaxy
+	ImportKrona
+	ImportMETAREP-BLAST
+	ImportMETAREP-EC
+	ImportMGRAST
+	ImportPhymmBL
+	ImportRDP
+	ImportRDPComparison
+	ImportTaxonomy
+	ImportText
+	ImportXML
+))
+{
+	if ( system('ln', '-sf', "$scriptPath/$script.pl", "$path/bin/kt$script") )
+	{
+		linkFail("$path/bin");
+	}
+}
+
+if ( defined $taxonomyDir )
+{
+	if ( ! -e $taxonomyDir )
+	{
+		ktDie("$taxonomyDir does not exist.");
+	}
+	
+	if ( -e 'taxonomy')
+	{
+		system('rm -r taxonomy');
+	}
+	
+	print "Linking taxonomy to $taxonomyDir...\n";
+	system('ln -s -f -F ' . $taxonomyDir . ' taxonomy');
+}
+
+print '
+Installation complete.
+
+Run ./updateTaxonomy.sh to use scripts that rely on NCBI taxonomy:
+   ktClassifyBLAST
+   ktGetLCA
+   ktGetTaxInfo
+   ktImportBLAST
+   ktImportTaxonomy
+   ktImportMETAREP-BLAST
+
+Run ./updateAccessions.sh to use scripts that get taxonomy IDs from accessions:
+   ktClassifyBLAST
+   ktGetTaxIDFromAcc
+   ktImportBLAST
+';
+
+sub createDir
+{
+	my ($dir) = @_;
+	
+	if ( ! -e $dir )
+	{
+		mkdir $dir or ktDie("$dir does not exist and couldn't create");
+	}
+}
+
+sub ktDie
+{
+	my ($error) = @_;
+	
+	print "\nERROR: $error\n\n";
+	exit 1;
+}
+
+sub linkFail
+{
+	my ($path) = @_;
+	
+	ktDie("Couldn't link files to $path.  Do you have permission?\n(Use \"--prefix <path>\" to change install location)");
+	exit 1;
+}
diff --git a/KronaTools/lib/KronaTools.pm b/KronaTools/lib/KronaTools.pm
new file mode 100644
index 0000000..584b26b
--- /dev/null
+++ b/KronaTools/lib/KronaTools.pm
@@ -0,0 +1,2361 @@
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+use strict;
+
+package KronaTools;
+
+use Getopt::Long;
+use File::Basename;
+use File::Path;
+
+use base 'Exporter';
+use Cwd 'abs_path';
+
+my $libPath;
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	$libPath = dirname(abs_path(__FILE__));
+}
+my $taxonomyDir = $libPath;
+$taxonomyDir =~ s/lib$/taxonomy/;
+my $ecFile = "$libPath/../data/ec.tsv";
+my $useMembers; # set by addMember()
+
+# public subroutines
+#
+our @EXPORT = qw
+(
+	addByEC
+	addByLineage
+	addByTaxID
+	addXML
+	classifyBlast
+	default
+	getAccFromSeqID
+	getKronaOptions
+	getOption
+	getOptionString
+	getScoreName
+	getScriptName
+	getTaxDepth
+	getTaxInfo
+	getTaxName
+	getTaxParent
+	getTaxRank
+	getTaxIDFromAcc
+	htmlFooter
+	htmlHeader
+	ktDie
+	ktWarn
+	loadEC
+	loadMagnitudes
+	loadTaxonomy
+	newTree
+	parseDataset
+	printColumns
+	printHeader
+	printOptions
+	printWarnings
+	printUsage
+	setOption
+	taxContains
+	taxLowestCommonAncestor
+	taxIDExists
+	writeTree
+);
+
+
+###########
+# Options #
+###########
+
+# The container for option values, initialized with global defaults.
+#
+my %options =
+(
+	'collapse' => 1,
+	'color' => 0,
+	'ecCol' => 2,
+	'hueBad' => 0,
+	'hueGood' => 120,
+	'key' => 1,
+	'queryCol' => 1,
+	'scoreCol' => 3,
+	'standalone' => 1,
+	'taxCol' => 2,
+	'taxonomy' => $taxonomyDir,
+	'threshold' => 3
+);
+
+# Option format codes to pass to GetOptions (and to be parsed for display).
+# Multiple options can use the same option letter, as long as they don't
+# conflict within any given script.
+#
+my %optionFormats =
+(
+	'standalone' =>
+		'a',
+	'bitScore' =>
+		'b',
+	'combine' =>
+		'c',
+	'depth' =>
+		'd=i',
+	'ecCol' =>
+		'e=i',
+	'factor' =>
+		'e=f',
+	'include' =>
+		'i',
+	'noRank' =>
+		'k',
+	'local' =>
+		'l',
+	'magCol' =>
+		'm=i',
+	'minConfidence' =>
+		'm=f',
+	'name' =>
+		'n=s',
+	'out' =>
+		'o=s',
+	'percentIdentity' =>
+		'p',
+	'phymm' =>
+		'p',
+	'postUrl' =>
+		'post=s',
+	'noMag' =>
+		'q',
+	'queryCol' =>
+		'q=i',
+	'postUrl' =>
+		'qp=s',
+	'random' =>
+		'r',
+	'scoreCol' =>
+		's=i',
+	'summarize' =>
+		's',
+	'taxCol' =>
+		't=i',
+	'threshold' =>
+		't=f',
+	'taxonomy' =>
+		'tax=s',
+	'url' =>
+		'u=s',
+	'verbose' =>
+		'v',
+	'hueBad' =>
+		'x=i',
+	'hueGood' =>
+		'y=i'
+);
+
+# how option arguments should be displayed based on format codes in %optionFormats
+#
+my %optionTypes =
+(
+	's' => 'string',
+	'f' => 'number',
+	'i' => 'integer'
+);
+
+# option descriptions to show in printOptions()
+#
+my %optionDescriptions =
+(
+	'bitScore' => 'Use bit score for average scores instead of log[10] e-value.',
+	'combine' => 'Combine data from each file, rather than creating separate datasets within the chart.',
+	'depth' => 'Maximum depth of wedges to include in the chart.',
+	'ecCol' => 'Column of input files to use as EC number.',
+	'factor' => 'E-value factor for determining "best" hits. A bit score difference threshold (-t) is recommended instead to avoid comparing e-values that BLAST reports as 0 due to floating point underflow. However, an e-value factor should be used if the input is a concatination of BLASTs against different databases. ',
+	'hueBad' => 'Hue (0-360) for "bad" scores.',
+	'hueGood' => 'Hue (0-360) for "good" scores.',
+	'percentIdentity' => 'Use percent identity for average scores instead of log[10] e-value.',
+	'include' => 'Include a wedge for queries with no hits.',
+	'local' => 'Use resources from the local KronaTools installation instead of bundling them with charts (charts will be smaller but will only work on this computer).',
+	'magCol' => 'Column of input files to use as magnitude. If magnitude files are specified, their magnitudes will override those in this column.',
+	'minConfidence' => 'Minimum confidence. Each query sequence will only be added to taxa that were predicted with a confidence score of at least this value.',
+	'name' => 'Name of the highest level.',
+	'noMag' => 'Files do not have a field for quantity.',
+	'noRank' => 'Allow assignments to taxa with ranks labeled "no rank" (instead of moving up to parent).',
+	'out' => 'Output file name.',
+	'phymm' => 'Input is phymm only (no confidence scores).',
+	'postUrl' => 'Url to send query IDs to (instead of listing them) for each wedge. The query IDs will be sent as a comma separated list in the POST variable "queries", with the current dataset index (from 0) in the POST variable "dataset". The url can include additional variables encoded via GET.',
+	'queryCol' => 'Column of input files to use as query ID. Required if magnitude files are specified.',
+	'random' => 'Pick from the best hits randomly instead of finding the lowest common ancestor.',
+	'scoreCol' => 'Column of input files to use as score.',
+	'standalone' => 'Create a standalone chart, which includes Krona resources and does not require an Internet connection or KronaTools installation to view.',
+	'summarize' => 'Summarize counts and average scores by taxonomy ID.',
+	'taxCol' => 'Column of input files to use as taxonomy ID.',
+	'taxonomy' => 'Path to directory containing a taxonomy database to use.',
+	'threshold' => 'Threshold for bit score differences when determining "best" hits. Hits with scores that are within this distance of the highest score will be included when computing the lowest common ancestor (or picking randomly if -r is specified).',
+	'url' => 'URL of Krona resources to use instead of bundling them with the chart (e.g. "http://krona.sourceforge.net"). Reduces size of charts and allows updates, though charts will not work without access to this URL.',
+	'verbose' => 'Verbose.'
+);
+
+
+#############
+# Arguments #
+#############
+
+# how common arguments should be displayed
+#
+our %argumentNames =
+(
+	'blast' => 'blast_output',
+	'magnitude' => 'magnitudes',
+	'metarep' => 'metarep_folder',
+	'name' => 'name',
+);
+
+# how common arguments should be described
+#
+our %argumentDescriptions =
+(
+	'blast' =>
+'File containing BLAST results in tabular format ("Hit table (text)" when
+downloading from NCBI). If running BLAST locally, subject IDs in the local
+database must contain accession numbers, either bare or in the fourth field of
+the pipe-separated ("gi|12345|xx|ABC123.1|") format.',
+	'magnitude' =>
+'Optional file listing query IDs with magnitudes, separated by tabs. This can
+be used to account for read length or contig depth to obtain a more accurate
+representation of abundance. By default, query sequences without specified
+magnitudes will be assigned a magnitude of 1. Magnitude files for assemblies in
+ACE format can be created with ktGetContigMagnitudes.',
+	'metarep' =>
+'Unpacked METAREP data folder.',
+	'name' =>
+'A name to show in the list of datasets in the Krona chart (if multiple input
+files are present and ' . getOptionString('combine') . ' is not specified). By
+default, the basename of the file will be used.',
+);
+
+
+####################
+# Global constants #
+####################
+
+our $version = '2.7';
+my $javascriptVersion = '2.0';
+my $javascript = "src/krona-$javascriptVersion.js";
+my $hiddenImage = 'img/hidden.png';
+my $favicon = 'img/favicon.ico';
+my $loadingImage = 'img/loading.gif';
+my $logo = 'img/logo-med.png';
+my $taxonomyHrefBase = 'http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=info&id=';
+my $ecHrefBase = 'http://www.chem.qmul.ac.uk/iubmb/enzyme/EC';
+my $suppDirSuffix = '.files';
+my $suppEnableFile = 'enable.js';
+my $fileTaxonomy = 'taxonomy.tab';
+my $fileTaxByAcc = 'all.accession2taxid.sorted';
+my $memberLimitDataset = 10000;
+my $memberLimitTotal = 100000;
+my $columns = `tput cols`;
+our $minEVal = -450;
+
+
+#################
+# Lookup tables #
+#################
+
+my @taxDepths;
+my @taxParents;
+my @taxRanks;
+my @taxNames;
+my %taxInfoByID;
+my %taxIDByAcc;
+my %ecNames;
+my %invalidAccs;
+my %missingAccs;
+my %missingTaxIDs;
+
+
+############
+# Exported #
+############
+
+
+sub addByEC
+{
+	# add based on an EC number string
+	#
+	# Options used:
+	# depth
+	my
+	(
+		$node, # hash ref
+		$set, # integer
+		$ec, # array ref of ec number components (no dots)
+		$queryID, # (optional) string
+		$magnitude, # (optional) number
+		$score, # (optional) number
+		
+		# for recursion only
+		#
+		$depth
+	) = @_;
+	
+	if ( ! %ecNames )
+	{
+		ktDie('EC data not loaded. "loadEC()" must be called first.');
+	}
+	
+	$magnitude = default($magnitude, 1);
+	
+	$node->{'magnitude'}[$set] += $magnitude;
+	$node->{'count'}[$set]++;
+	
+	if ( ! @$ec )
+	{
+		$node->{'children'}{'No hits'}{'magnitude'}[$set] += $magnitude;
+		$node->{'children'}{'No hits'}{'count'}[$set]++;
+		
+		if ( ! defined $node->{'children'}{'No hits'}{'scoreCount'} )
+		{
+			$node->{'children'}{'No hits'}{'scoreCount'}[0] = 0;
+		}
+		
+		if ( $queryID )
+		{
+			addMember($node->{'children'}{'No hits'}, $set, $queryID);
+		}
+		
+		return;
+	}
+	
+	if
+	(
+		$depth < @$ec &&
+		( ! $options{'depth'} || $depth < $options{'depth'} )
+	)
+	{
+		my $ecString = join '.', @$ec[0..$depth];
+		my $name = $ecNames{$ecString};
+		my $child;
+		
+		if ( defined $node->{'children'}{$name} )
+		{
+			$child = $node->{'children'}{$name};
+		}
+		else
+		{
+			my %newChild = ();
+			
+			$node->{'children'}{$name} = \%newChild;
+			$child = $node->{'children'}{$name};
+			
+			$child->{'ec'}[0] = $ecString;
+		}
+		
+		if ( defined $score )
+		{
+			${$child->{'scoreTotal'}}[$set] += $score * $magnitude;
+			${$child->{'scoreCount'}}[$set] += $magnitude;
+		}
+		
+		addByEC($child, $set, $ec, $queryID, $magnitude, $score, $depth + 1);
+	}
+	else
+	{
+		if ( $queryID )
+		{
+			addMember($node, $set, $queryID);
+		}
+		
+		$node->{'unassigned'}[$set]++;
+		$node->{'magnitudeUnassigned'}[$set] += $magnitude;
+	}
+}
+
+sub addByLineage
+{
+	# add based on an explicit lineage
+	#
+	# Options used:
+	# depth, minConfidence, leafAdd
+	
+	my
+	(
+		$node, # hash ref
+		$dataset, # integer
+		$lineage, # array ref
+		$queryID, # (optional) string
+		$magnitude, # (optional) number
+		$scores, # (optional) number or array ref
+		$ranks, # (optional) array ref
+		
+		# for recursion only
+		#
+		$index, # current index of input arrays
+		$depth # our node depth (since input array elements can be skipped)
+	) = @_;
+	
+	$magnitude = default($magnitude, 1);
+	
+	if ( $options{'leafAdd'} )
+	{
+		# magnitudes are already summarized; instead of adding magnitude to
+		# ancestors, directly set it for the lowest level of the lineage.
+		
+		if ( $index == @$lineage )
+		{
+			$node->{'magnitude'}[$dataset] = $magnitude;
+		}
+	}
+	else
+	{
+		$node->{'magnitude'}[$dataset] += $magnitude;
+	}
+	
+	$node->{'count'}[$dataset]++;
+	
+	# skip nameless nodes
+	#
+	while ( $$lineage[$index] eq '' && $index < @$lineage )
+	{
+		$index++;
+	}
+	
+	my $score;
+	
+	if ( ref($scores) eq 'ARRAY' )
+	{
+		$score = $$scores[$index];
+	}
+	else
+	{
+		$score = $scores;
+	}
+	
+	if
+	(
+		$index < @$lineage &&
+		( ! $options{'depth'} || $depth < $options{'depth'} ) &&
+		(
+			! defined $options{'minConfidence'} ||
+			! defined $score ||
+			$score >= $options{'minConfidence'}
+		)
+	)
+	{
+		my $name = $$lineage[$index];
+		my $child;
+		
+		if ( defined ${$node}{'children'}{$name} )
+		{
+			$child = ${$node}{'children'}{$name};
+		}
+		else
+		{
+			my %newHash = ();
+			${$node}{'children'}{$name} = \%newHash;
+			$child = ${$node}{'children'}{$name};
+			
+			if ( $ranks )
+			{
+				$child->{'rank'}[0] = $$ranks[$index];
+			}
+		}
+		
+		if ( defined $score )
+		{
+			if ( $options{'leafAdd'} )
+			{
+				# instead of averaging score for ancestors, directly set it
+				# for the lowest level of the lineage.
+				
+				if ( $index == @$lineage - 1 )
+				{
+					$child->{'scoreTotal'}[$dataset] = $score;
+					$child->{'scoreCount'}[$dataset] = 1;
+				}
+			}
+			else
+			{
+				$child->{'scoreTotal'}[$dataset] += $score * $magnitude;
+				$child->{'scoreCount'}[$dataset] += $magnitude;
+			}
+		}
+		
+		addByLineage
+		(
+			$child,
+			$dataset,
+			$lineage,
+			$queryID,
+			$magnitude,
+			$scores,
+			$ranks,
+			$index + 1,
+			$depth + 1
+		);
+	}
+	elsif ( ! $options{'leafAdd'} )
+	{
+		if ( $queryID )
+		{
+			addMember($node, $dataset, $queryID);
+		}
+		
+		$node->{'unassigned'}[$dataset]++;
+		$node->{'magnitudeUnassigned'}[$dataset] += $magnitude;
+	}
+}
+
+sub addByTaxID
+{
+	# add based on NCBI taxonomy ID
+	#
+	# Options used:
+	# depth
+	
+	my
+	(
+		$node, # hash ref
+		$set, # integer
+		$taxID, # integer
+		$queryID, # string (optional)
+		$magnitude, # number (optional)
+		$score, # number (optional)
+		
+		# recusive only
+		#
+		$assigned
+	) = @_;
+	
+	$magnitude = default($magnitude, 1);
+	
+	if ( $taxID != 0 && ! defined $taxDepths[$taxID] )
+	{
+		$missingTaxIDs{$taxID} = 1;
+		$taxID = 1; # unknown tax ID; set to root
+	}
+	
+	if ( $taxID == 0 )
+	{
+		$node->{'count'}[$set]++;
+		$node->{'children'}{'No hits'}{'count'}[$set]++;
+		
+		my $child = $node->{'children'}{'No hits'};
+		
+		$node->{'magnitude'}[$set] += $magnitude;
+		$child->{'magnitude'}[$set] += $magnitude;
+		
+		if ( ! defined $child->{'scoreCount'} )
+		{
+			$child->{'scoreCount'}[0] = 0;
+		}
+		
+		if ( $queryID )
+		{
+			addMember($child, $set, $queryID);
+		}
+		
+		return;
+	}
+	
+	# move up to depth and skip unranked taxonomy nodes
+	#
+	while
+	(
+		! $options{'noRank'} && $taxID > 1 && $taxRanks[$taxID] eq 'no rank' ||
+		$options{'depth'} && $taxDepths[$taxID] > $options{'depth'}
+	)
+	{
+		$taxID = $taxParents[$taxID];
+	}
+	
+	# get parent recursively
+	#
+	my $parent;
+	my $parentID = $taxID;
+	
+	do
+	{
+		$parentID = getTaxParent($parentID);
+	}
+	while (! $options{'noRank'} && $parentID > 1 && getTaxRank($parentID) eq 'no rank');
+	
+	#
+	if ( $parentID != 1 )#$taxID )
+	{
+		$parent = addByTaxID($node, $set, $parentID, undef, $magnitude, $score, 1);
+	}
+	else
+	{
+		$parent = $node;
+		$parent->{'count'}[$set]++;
+		$parent->{'magnitude'}[$set] += $magnitude;
+	}
+	
+	# add this node to parent
+	#
+	if ( $taxID == 1 )
+	{
+		if ( $queryID )
+		{
+			addMember($parent, $set, $queryID);
+		}
+		
+		$parent->{'unassigned'}[$set]++;
+		$parent->{'magnitudeUnassigned'}[$set] += $magnitude;
+	}
+	else
+	{
+		my $name = $taxNames[$taxID];
+		
+		my $child;
+		
+		if ( defined $parent->{'children'}{$name} )
+		{
+			$child = $parent->{'children'}{$name};
+		}
+		else
+		{
+			my %newChild = ();
+			
+			$parent->{'children'}{$name} = \%newChild;
+			$child = $parent->{'children'}{$name};
+			
+			$child->{'rank'}[0] = $taxRanks[$taxID];
+			$child->{'taxon'}[0] = taxonLink($taxID);
+		}
+		
+		if ( $queryID )
+		{
+			addMember($child, $set, $queryID);
+		}
+		
+		${$child->{'count'}}[$set]++;
+		
+		if ( ! $assigned )
+		{
+			$child->{'unassigned'}[$set]++;
+			$child->{'magnitudeUnassigned'}[$set] += $magnitude;
+		}
+		
+		${$child->{'magnitude'}}[$set] += $magnitude;
+		
+		if ( defined $score )
+		{
+			$magnitude = default($magnitude, 1);
+			${$child->{'scoreTotal'}}[$set] += $score * $magnitude;
+			${$child->{'scoreCount'}}[$set] += $magnitude;
+		}
+		
+		return $child;
+	}
+}
+
+sub addXML
+{
+	my # parameters
+	(
+		$node,
+		$xml,
+		$dataset,
+		$file
+	) = @_;
+	
+	while ( (my $line = <$xml>) !~ /<\/node>/ )
+	{
+		if ( $line =~ /<node name="([^"]+)">/ )
+		{
+			my $child = $1;
+			
+			if ( ! defined $node->{'children'}{$child} )
+			{
+				my %newChild = ();
+				$node->{'children'}{$child} = \%newChild;
+			}
+			
+			addXML($node->{'children'}{$child}, $xml, $dataset, $file);
+		}
+		elsif ( $line =~ /<members>/ )
+		{
+			if ( $line =~ /<val>(.*)<\/val>/ )
+			{
+				my @members = split /<\/val><val>/, $1;
+				my $offset = 0;
+				
+				for ( my $i = 0; $i < @members; $i++ )
+				{
+					if ( $members[$i] eq "" )
+					{
+						next;
+					}
+					
+					my $fileMembers = "$file.files/$members[$i]";
+					
+					if ( open MEMBERS, $fileMembers )
+					{
+						while ( <MEMBERS> )
+						{
+							if ( /(data\(')?(.+)\\n\\/ )
+							{
+								addMember($node, $dataset + $i, $2);
+							}
+						}
+					
+						close MEMBERS;
+					}
+				}
+			}
+			
+			while ( $line !~ /<\/members>/ )
+			{
+				my $offset = 0;
+				
+				if ( $line =~ /<vals><val>(.*)<\/val><\/vals>/ )
+				{
+					my @members = split /<\/val><val>/, $1;
+					
+					for ( my $i = 0; $i < @members; $i++ )
+					{
+						addMember($node, $dataset + $offset, $members[$i]);
+					}
+					
+					$offset++;
+				}
+				
+				$line = <$xml>;
+			}
+		}
+		elsif ( $line =~ /<(rank|taxon)><val>(.*)<\/val><\/\1>/ )
+		{
+			$node->{$1}[0] = $2;
+		}
+		elsif ( $line =~ /<(count|score|magnitude)><val>(.*)<\/val><\/\1>/ )
+		{
+			my @vals = split /<\/val><val>/, $2;
+			
+			for ( my $i = 0; $i < @vals; $i++ )
+			{
+				if ( $1 eq 'score' )
+				{
+					$node->{'scoreTotal'}[$dataset + $i] = $vals[$i];
+					$node->{'scoreCount'}[$dataset + $i] = 1;
+				}
+				else
+				{
+					$node->{$1}[$dataset + $i] = $vals[$i];
+				}
+			}
+		}
+		elsif ( $line =~ /<\/node>/ )
+		{
+			return;
+		}
+	}
+}
+
+sub classifyBlast
+{
+	# taxonomically classifies BLAST results based on LCA (or random selection)
+	# of 'best' hits.
+	#
+	# Options used: bitScore, factor, include, percentIdentity, random, score
+	
+	my # parameters
+	(
+		$fileName, # file with tabular BLAST results
+		
+		# hash refs to be populated with results (keyed by query ID)
+		#
+		$taxIDs,
+		$scores
+	) = @_;
+	
+	open BLAST, "<$fileName" or ktDie("Could not open $fileName\n");
+	
+	my $lastQueryID;
+	my $topScore;
+	my $topEVal;
+	my $ties;
+	my $taxID;
+	my %lcaSet;
+	my $totalScore;
+	my $zeroEVal;
+	
+	while ( 1 )
+	{
+		my $line = <BLAST>;
+		
+		chomp $line;
+		
+		if ( $line =~ /^#/ )
+		{
+			if ( $line =~ /Query: ([\S]+)/ )
+			{
+				# Initialize taxID and score in case this query has no hits
+				
+				$taxIDs->{$1} = -1;
+				$scores->{$1} = 0;
+			}
+			
+			next;
+		}
+		
+		my
+		(
+			$queryID,
+			$hitID,
+			$identity,
+			$length,
+			$mismatches,
+			$gaps,
+			$queryStart,
+			$queryEnd,
+			$subjectStart,
+			$subjectEnd,
+			$eVal,
+			$bitScore
+		) = split /\t/, $line;
+		
+		if ( $queryID ne $lastQueryID )
+		{
+			if
+			(
+				! defined $lastQueryID &&
+				! defined $taxIDs->{$queryID} &&
+				$options{'include'}
+			)
+			{
+				ktWarn("-i specified but $fileName does not contain comment lines. Queries with no hits will not be included for this file."); 
+			}
+			
+			if (  $ties )
+			{
+				# add the chosen hit from the last queryID
+				
+				if ( ! $options{'random'} )
+				{
+					$taxID = taxLowestCommonAncestor(keys %lcaSet)
+				}
+				
+				$taxIDs->{$lastQueryID} = $taxID;
+				$scores->{$lastQueryID} = $totalScore / $ties;
+			}
+			
+			$ties = 0;
+			$totalScore = 0;
+			%lcaSet = ();
+		}
+		
+		if ( ! defined $hitID )
+		{
+			last; # EOF
+		}
+		
+		my $acc = getAccFromSeqID($hitID);
+		
+		if ( ! defined $acc )
+		{
+			$lastQueryID = $queryID;
+			next;
+		}
+		
+		if # this is a 'best' hit if...
+		(
+			$queryID ne $lastQueryID || # new query ID (including null at EOF)
+			$bitScore > $topScore - $options{'threshold'} || # within score threshold
+			$options{'factor'} && $eVal <= $options{'factor'} * $topEVal # within e-val factor
+		)
+		{
+			# add score for average
+			#
+			if ( $options{'percentIdentity'} )
+			{
+				$totalScore += $identity;
+			}
+			elsif ( $options{'bitScore'} )
+			{
+				$totalScore += $bitScore;
+			}
+			else
+			{
+				if ( $eVal > 0 )
+				{
+					$totalScore += (log $eVal) / log 10;
+				}
+				else
+				{
+					$totalScore += $minEVal;
+					$zeroEVal = 1;
+				}
+			}
+			#
+			$ties++;
+			
+			if # use this hit if...
+			(
+				! $options{'random'} || # using LCA
+				$queryID ne $lastQueryID || # new query ID
+				int(rand($ties)) == 0 # randomly chosen to replace other hit
+			)
+			{
+				my $newTaxID = getTaxIDFromAcc($acc);
+				
+				if ( ! $newTaxID || ! defined $taxParents[$newTaxID] )
+				{
+					$newTaxID = 1;
+				}
+				
+				if ( $options{'random'} )
+				{
+					$taxID = $newTaxID;
+				}
+				else
+				{
+					$lcaSet{$newTaxID} = 1;
+				}
+			}
+		}
+		
+		if ( $queryID ne $lastQueryID )
+		{
+			$topScore = $bitScore;
+			$topEVal = $eVal;
+		}
+		
+		$lastQueryID = $queryID;
+	}
+	
+	if ( $zeroEVal )
+	{
+		ktWarn("\"$fileName\" had e-values of 0. Approximated log[10] of 0 as $minEVal.");
+	}
+}	
+
+sub default
+{
+	# Use a variable if it is defined or return a default value if it is not.
+	
+	my ($value, $default) = @_;
+	
+	if ( defined $value )
+	{
+		return $value;
+	}
+	else
+	{
+		return $default;
+	}
+}
+
+sub getAccFromSeqID
+{
+	my ($seqID) = @_;
+	
+	$seqID =~ /^>?(\S+)/;
+	
+	my $acc = $1;
+	
+	if ( $acc =~ /\|/ )
+	{
+		$acc = (split /\|/, $acc)[3];
+	}
+	
+	if ( $acc !~ /^\d+$/ && $acc !~ /^[A-Z]+_?[A-Z]*\d+(\.\d+)?$/ )
+	{
+		$invalidAccs{$acc} = 1;
+		return undef;
+	}
+	
+	return $acc;
+}
+
+sub getKronaOptions
+{
+	# Parse command line arguments and set options using Getopt::Long
+	
+	my @options = @_;
+	
+	my %params;
+	
+	foreach my $option ( @options )
+	{
+		$params{$optionFormats{$option}} = \$options{$option};
+	}
+	
+	if ( ! GetOptions(%params) )
+	{
+		exit;
+	}
+	
+	validateOptions();
+}
+
+sub getOption
+{
+	my ($option) = @_;
+	
+	return $options{$option};
+}
+
+sub getOptionString
+{
+	# Make a string from the option format to show as the command line option
+	
+	my ($option) = @_;
+	
+	my ($short, $type) = split /=/, $optionFormats{$option};
+	my $string = "[-$short";
+	
+	if ( defined $type )
+	{
+		$string .= " <$optionTypes{$type}>";
+	}
+	
+	$string .= ']';
+	
+	return $string;
+}
+
+sub getScoreName
+{
+	if ( getOption('bitScore') )
+	{
+		return 'Avg. bit score';
+	}
+	elsif ( getOption('percentIdentity') )
+	{
+		return 'Avg. % identity';
+	}
+	else
+	{
+		return 'Avg. log e-value';
+	}
+}
+
+sub getScriptName
+{
+	return fileparse($0);
+}
+
+sub getTaxDepth
+{
+	my ($taxID) = @_;
+	
+	if ( @taxDepths )
+	{
+		return $taxDepths[$taxID];
+	}
+	else
+	{
+		return (getTaxInfo($taxID))[1];
+	}
+}
+
+sub getTaxInfo
+{
+	# gets info from a line in taxonomy.tab with it being loaded (via binary search)
+	
+	my ($tax) = @_;
+	
+	$tax = int($tax);
+	
+	if ( defined $taxInfoByID{$tax} )
+	{
+		return @{$taxInfoByID{$tax}};
+	}
+	
+	my $size = -s "$options{'taxonomy'}/$fileTaxonomy";
+	my $taxCur;
+	my @info = ($tax);
+	
+	if ( ! open TAX, "<$options{'taxonomy'}/$fileTaxonomy" )
+	{
+		print "ERROR: Taxonomy not found in $options{'taxonomy'}. Was updateTaxonomy.sh run?\n";
+		exit 1;
+	}
+	
+	my $min = 0;
+	my $max = $size;
+	
+	while ( $taxCur ne $tax )
+	{
+		my $posNew = int(($min + $max) / 2);
+		
+		seek TAX, $posNew, 0;
+		
+		if ( $posNew > 0 )
+		{
+			<TAX>; # eat up to newline
+		}
+		
+		my $line = <TAX>;
+		
+		my $taxNew;
+		
+		$line =~ /^(\d+)/;
+		$taxNew = $1;
+		
+		if ( $tax == $taxNew )
+		{
+			chomp $line;
+			@info = split /\t/, $line;
+			last;
+		}
+		elsif ( $posNew == $min )
+		{
+			last;
+		}
+		
+		if ( $tax > $taxNew && $taxCur != $taxNew && $taxNew )
+		{
+			$min = $posNew;
+		}
+		else
+		{
+			$max = $posNew;
+		}
+		
+		$taxCur = $taxNew;
+	}
+	
+	close TAX;
+	
+	$taxInfoByID{$tax} = \@info;
+	
+	return @info;
+}
+
+sub getTaxName
+{
+	my ($taxID) = @_;
+	
+	if ( @taxNames )
+	{
+		return $taxNames[$taxID];
+	}
+	else
+	{
+		return (getTaxInfo($taxID))[4];
+	}
+}
+
+sub getTaxParent
+{
+	my ($taxID) = @_;
+	
+	if ( @taxParents )
+	{
+		return $taxParents[$taxID];
+	}
+	else
+	{
+		return (getTaxInfo($taxID))[2];
+	}
+}
+
+sub getTaxRank
+{
+	my ($taxID) = @_;
+	
+	if ( @taxRanks )
+	{
+		return $taxRanks[$taxID];
+	}
+	else
+	{
+		return (getTaxInfo($taxID))[3];
+	}
+}
+
+sub getTaxIDFromAcc
+{
+	my ($acc) = @_;
+	
+	if ( $acc =~ /^\d+$/ )
+	{
+		return $acc;
+	}
+	
+	$acc =~ s/\.\d+$//;
+	
+	if ( defined $taxIDByAcc{$acc} )
+	{
+		return $taxIDByAcc{$acc};
+	}
+	
+	my $size = -s "$options{'taxonomy'}/$fileTaxByAcc";
+	my $accCur;
+	my $taxID;
+	
+	if ( ! open ACC, "<$options{'taxonomy'}/$fileTaxByAcc" )
+	{
+		print "ERROR: Sorted accession to taxID list not found. Was updateAccessions.sh run?\n";
+		exit 1;
+	}
+	
+	my $min = 0;
+	my $max = $size;
+	
+	#print "ACC: $acc\n";
+	
+	while ( $acc ne $accCur && $min < $max )
+	{
+		my $posNew = int(($min + $max) / 2);
+		
+		seek ACC, $posNew, 0;
+		
+		if ( $posNew != $min )
+		{
+			<ACC>; # eat up to newline
+		}
+		
+		my $line = <ACC>;
+		
+		my $accNew;
+		($accNew, $taxID) = split /\t/, $line;
+		
+		if ( $acc gt $accNew && $accCur ne $accNew && $accNew )
+		{
+			if ( $accNew )
+			{
+				$posNew = tell ACC;
+			}
+			
+			$min = $posNew;
+			
+			if ( $min >= $max )
+			{
+				$max = $min + 1;
+			}
+		}
+		else
+		{
+			$max = $posNew;
+		}
+		
+		$accCur = $accNew;
+	}
+	
+	close ACC;
+	
+	chomp $taxID;
+	
+	if ( $accCur ne $acc )
+	{
+		$missingAccs{$acc} = 1;
+		$taxID = 0;
+	}
+	
+	$taxIDByAcc{$acc} = $taxID;
+	
+	return $taxIDByAcc{$acc};
+}
+
+sub htmlFooter
+{
+	return "</div></body></html>\n";
+}
+
+sub htmlHeader
+{
+	my $path;
+	my $notFound;
+	my $script;
+	
+	if ( $options{'standalone'} && ! $options{'local'} &&  ! $options{'url'} )
+	{
+		$script =
+			indent(2) . "<script language=\"javascript\" type=\"text/javascript\">\n" .
+			slurp("$libPath/../$javascript") . "\n" .
+			indent(2) . "</script>\n";
+		
+		$hiddenImage = slurp("$libPath/../img/hidden.uri");
+		$loadingImage = slurp("$libPath/../img/loading.uri");
+		$favicon = slurp("$libPath/../img/favicon.uri");
+		$logo = slurp("$libPath/../img/logo-med.uri");
+	}
+	else
+	{
+		if ( $options{'local'} )
+		{
+			$path = "$libPath/../";
+			$notFound = "This is a local chart and must be viewed on the computer it was created with.";
+		}
+		else
+		{
+			$path = "$options{'url'}/";
+			$notFound = "Could not get resources from \\\"$options{'url'}\\\".";
+		}
+		
+		$script = indent(2) . "<script src=\"$path$javascript\"></script>\n";
+	}
+	
+	return
+		'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . "\n" .
+		'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">' . "\n" .
+		indent(1) . "<head>\n" .
+			indent(2) . "<meta charset=\"utf-8\"/>\n" .
+#			indent(2) . "<base href=\"$path\" target=\"_blank\"/>\n" .
+			indent(2) . "<link rel=\"shortcut icon\" href=\"$path$favicon\"/>\n" .
+			indent(2) . "<script id=\"notfound\">window.onload=function(){document.body.innerHTML=\"$notFound\"}</script>\n" .
+			$script .
+		indent(1) . "</head>\n" .
+		indent(1) . "<body>\n" .
+			indent(2) . "<img id=\"hiddenImage\" src=\"$path$hiddenImage\" style=\"display:none\"/>\n" .
+			indent(2) . "<img id=\"loadingImage\" src=\"$path$loadingImage\" style=\"display:none\"/>\n" .
+			indent(2) . "<img id=\"logo\" src=\"$path$logo\" style=\"display:none\"/>\n" .
+			indent(2) . "<noscript>Javascript must be enabled to view this page.</noscript>\n" .
+			indent(2) . "<div style=\"display:none\">\n";
+}
+
+sub ktDie
+{
+	my ($error) = @_;
+	
+	*STDOUT = *STDERR;
+	printColumns('[ ERROR ]', $error);
+	exit 1;
+}
+
+sub ktWarn
+{
+	my ($warning) = @_;
+	
+	*STDOUTOLD = *STDOUT;
+	*STDOUT = *STDERR;
+	printColumns('   [ WARNING ]', $warning);
+	*STDOUT = *STDOUTOLD
+}
+
+sub loadEC
+{
+	open EC, "<$ecFile" or die "$ecFile not found.";
+	
+	<EC>; # eat header
+	
+	while ( <EC> )
+	{
+		chomp;
+		my ($ec, $name) = split /\t/;
+		$ecNames{$ec} = $name;
+	}
+	
+	close EC;
+}
+
+sub loadMagnitudes
+{
+	# load magnitudes from a tab-delimited file listing query IDs and magnitudes
+	
+	my
+	(
+		$magFile, # file name
+		$magnitudes # hash ref (to be populated)
+	) = @_;
+	
+	open MAG, "<$magFile" or die "Couldn't load $magFile";
+	
+	while ( my $line = <MAG> )
+	{
+		chomp $line;
+		my ( $id, $mag ) = split /\t/, $line;
+		$magnitudes->{$id} = $mag;
+	}
+	
+	close MAG;
+}
+
+sub loadTaxonomy
+{
+	open INFO, "<$options{'taxonomy'}/$fileTaxonomy" or die
+		"Taxonomy not found in $options{'taxonomy'}. Was updateTaxonomy.sh run?";
+	
+	while ( my $line = <INFO> )
+	{
+		chomp $line;
+		my ($id, $depth, $parent, $rank, $name) = split /\t/, $line;
+		
+		$taxParents[$id] = $parent;
+		$taxDepths[$id] = $depth;
+		$taxRanks[$id] = $rank;
+		$taxNames[$id] = $name;
+	}
+	
+	if ( $taxParents[2] == 1 && $options{'noRank'} )
+	{
+		ktDie
+		(
+"Local taxonomy database is out of date and does not support the
+-$optionFormats{'noRank'} option. Update using updateTaxonomy.sh."
+		);
+	}
+	close INFO;
+}
+
+sub newTree
+{
+	my %tree = ();
+	return \%tree;
+}
+
+sub parseDataset
+{
+	my ($input) = @_;
+	
+	$input =~ /([^:,]+)(:([^,]+))?(,"?([^"]+)"?)?/;
+	
+	my ($file, $mag, $name) = ($1, $3, $5);
+	
+	if ( ! defined $name )
+	{
+		$name = fileparse($file, qr/\.[^.]*/); # get dataset name from file
+	}
+	
+	$name =~ s/</&lt;/g;
+	$name =~ s/>/&gt;/g;
+	
+	return ($file, $mag, $name);
+}
+
+sub printColumns
+{
+	# Prints headers and descriptions in two columns. Even indeces of the
+	# parameters should be headers (left column); odd indeces should be
+	# descriptions (right column).
+	
+	my @columns = @_;
+	
+	my $maxHeaderLength;
+	
+	for ( my $i = 0; $i < @columns; $i += 2 )
+	{
+		if ( length $columns[$i] > $maxHeaderLength )
+		{
+			$maxHeaderLength = length $columns[$i];
+		}
+	}
+	
+	for ( my $i = 0; $i < @columns; $i += 2 )
+	{
+		if ( $i > 0 )
+		{
+			print "\n";
+		}
+		
+		printHangingIndent
+		(
+			$columns[$i],
+			$columns[$i + 1],
+			$maxHeaderLength + 2
+		);
+	}
+}
+
+sub printHeader
+{
+	# Prints a string with decoration
+	
+	my ($header) = @_;
+	
+	my $width = length($header) + 2;
+	
+	#print ' ', '_' x $width, "\n";
+	#print '/ ', $header, " \\\n";
+	#print '\\', '_' x $width, "/\n\n";
+	my $prefix = '/ ';
+	my $fill = '_';
+	my $suffix = ' \\___';
+	my $fillLength = $columns - length($header) - length($prefix) - length($suffix);
+	print ' ' x ($fillLength + 1);
+	print '_' x $width;
+	print "\n";
+	print $fill x $fillLength;
+	print "$prefix$header$suffix";
+	print "\n\n";
+#	print "\n [=== $header ===]]]\n\n";
+}
+
+sub printOptions
+{
+	# Takes a list of standard KronaTools options (defined in
+	# %optionDescriptions) and prints them with their descriptions in columns.
+	
+	my @options = @_;
+	
+	my @optionColumns;
+	
+	foreach my $option ( @options )
+	{
+		my $header = '   ' . getOptionString($option);
+		my $description = $optionDescriptions{$option};
+		
+		if ( defined $options{$option} )
+		{
+			$description .= " [Default: '$options{$option}']";
+		}
+		
+		push @optionColumns, $header, $description;
+	}
+	
+	printHeader('Options');
+	printColumns(@optionColumns);
+	print "\n";
+}
+
+sub printWarnings
+{
+	if ( %invalidAccs )
+	{
+		ktWarn
+		(
+			"The following accessions were not in a valid format and were ignored:\n" .
+			join ' ', (keys %invalidAccs)
+		);
+		
+		%invalidAccs = ();
+	}
+	
+	if ( %missingAccs )
+	{
+		ktWarn
+		(
+			"The following accessions were not found in the local database (if they were recently added to NCBI, use updateAccessions.sh to update the local database):\n" .
+			join ' ', (keys %missingAccs)
+		);
+		
+		%missingAccs = ();
+	}
+	
+	if ( %missingTaxIDs )
+	{
+		ktWarn
+		(
+			"The following taxonomy IDs were not found in the local database and were set to root (if they were recently added to NCBI, use updateTaxonomy.sh to update the local database):\n" .
+			join ' ', (keys %missingTaxIDs)
+		);
+		
+		%missingTaxIDs = ();
+	}
+}
+
+sub printUsage
+{
+	my
+	(
+		$description, # script description
+		$argumentName,
+		$argumentDescription,
+		$useMagnitude, # show optional magnitude argument
+		$useName, # show optional name argument
+		$options # array ref of option names, defined in %option*
+	) = @_;
+	
+	my $scriptName = getScriptName();
+	
+	printHeader("KronaTools $version - $scriptName");
+	printHangingIndent('', $description);
+	printHeader('Usage');
+	print "$scriptName \\\n";
+	print "   [options] \\\n";
+	print
+		'   ', 
+		argumentString($argumentName, $useMagnitude, $useName, 1),
+		" \\\n";
+	print
+		'   ',
+		argumentString($argumentName, $useMagnitude, $useName, 2),
+		" \\\n";
+	print "   ...\n\n";
+	
+	my $combineString;
+	
+	foreach my $option ( @$options )
+	{
+		if ( $option eq 'combine' )
+		{
+			$combineString =
+' By default, separate datasets will be created for each input (see ' .
+getOptionString('combine') . ').'
+		}
+	}
+	
+	my @columns =
+	(
+		"   $argumentName",
+		$argumentDescription . $combineString
+	);
+	
+	if ( $useMagnitude )
+	{
+		push @columns,
+			"   $argumentNames{'magnitude'}",
+			$argumentDescriptions{'magnitude'};
+	}
+	
+	if ( $useName )
+	{
+		push @columns,
+			"   $argumentNames{'name'}",
+			$argumentDescriptions{'name'};
+	}
+	
+	printColumns(@columns);
+	printOptions(@$options);
+}
+
+sub setOption
+{
+	my ($option, $value) = @_;
+	
+	$options{$option} = $value;
+}
+
+sub taxContains
+{
+	# determines if $parent is an ancestor of (or equal to) $child
+	
+	my ($parent, $child) = @_;
+	
+	my $depthParent = $taxDepths[$parent];
+	
+	while ( $taxDepths[$child] > $taxDepths[$parent] )
+	{
+		$child = $taxParents[$child];
+	}
+	
+	return $parent == $child;
+}
+
+sub taxLowestCommonAncestor
+{
+	my @nodes = @_;
+	
+	# walk the nodes up to an equal depth
+	#
+	my $minDepth;
+	#
+	foreach my $node ( @nodes )
+	{
+		if ( ! taxIDExists($node) )
+		{
+			$missingTaxIDs{$node} = 1;
+			$node = 1;
+		}
+		
+		if ( ! defined $minDepth || getTaxDepth($node) < $minDepth )
+		{
+			$minDepth = getTaxDepth($node);
+		}
+	}
+	#
+	foreach my $node ( @nodes )
+	{
+		while ( getTaxDepth($node) > $minDepth )
+		{
+			$node = getTaxParent($node);
+		}
+	}
+	
+	my $done = 0;
+	
+	while ( ! $done )
+	{
+		$done = 1;
+		
+		my $prevNode;
+		
+		foreach my $node ( @nodes )
+		{
+			if ( defined $prevNode && $prevNode != $node )
+			{
+				$done = 0;
+				last;
+			}
+			
+			$prevNode = $node;
+		}
+		
+		if ( ! $done )
+		{
+			for ( my $i = 0; $i < @nodes; $i++ )
+			{
+				if ( ! defined getTaxParent($nodes[$i]) )
+				{
+					ktDie("Undefined parent for taxID $nodes[$i]");
+					return;
+				}
+				
+				$nodes[$i] = getTaxParent($nodes[$i]);
+			}
+		}
+	}
+	
+	return $nodes[0];
+}
+
+sub taxIDExists
+{
+	my ($taxID) = @_;
+	
+	return defined getTaxParent($taxID);
+}
+
+sub writeTree
+{
+	# Writes a Krona chart from a tree created with "addBy..." functions.
+	#
+	# Uses options: collapse, color, local, name, out, showKey, url
+	
+	my
+	(
+		$tree, # hash ref to head node of tree
+		$attributes, # array ref with names of attributes to display
+		$attributeDisplayNames, # array ref with display names for $attributes
+		$datasetNames, # array ref with names of datasets
+		$hueStart, # (optional) hue at the start of the gradient for score
+		$hueEnd # (optional) hue at the end of the gradient for score
+	) = @_;
+	
+	printWarnings();
+	
+	my %attributeHash;
+	
+	for ( my $i = 0; $i < @$attributes; $i++ )
+	{
+		$attributeHash{$$attributes[$i]} = $$attributeDisplayNames[$i];
+	}
+	
+	if ( $options{'leafAdd'} )
+	{
+		setInternalValues($tree);
+	}
+	
+	my ($valueStart, $valueEnd);
+	
+	if ( defined $hueStart && defined $hueEnd )
+	{
+		($valueStart, $valueEnd) = setScores($tree);
+	}
+	
+	# check if members should be stored in supplemental files
+	#
+	my $totalCount;
+	my $supp;
+	#
+	if ( $useMembers )
+	{
+		foreach my $count ( @{$tree->{'count'}} )
+		{
+			$totalCount += $count;
+		
+			if ( $count > $memberLimitDataset || $totalCount > $memberLimitTotal )
+			{
+				$supp = 1;
+				last;
+			}
+		}
+	}
+	
+	print "Writing $options{'out'}...\n";
+	
+	if ( $supp )
+	{
+		my $suppDir = $options{'out'} . $suppDirSuffix;
+		
+		ktWarn("Too many query IDs to store in chart; storing supplemental files in '$suppDir'.");
+		
+		if ( -e $suppDir )
+		{
+			ktWarn("Overwriting files in '$suppDir'.");
+			rmtree $suppDir or ktDie("Could not remove '$suppDir'.");
+		}
+		
+		mkdir $suppDir or ktDie("Could not create $suppDir");
+		
+		open SUPP, ">$suppDir/$suppEnableFile" or ktDie("Could not write file to '$suppDir'");
+		print SUPP "enableData();";
+		close SUPP;
+	}
+	
+	open OUT, ">$options{'out'}";
+	print OUT htmlHeader();
+	print OUT dataHeader
+	(
+		defined $attributeHash{'magnitude'} ? 'magnitude' : 'count',
+		$attributes,
+		$attributeDisplayNames,
+		$datasetNames,
+		'unassigned',
+		'count',
+		defined $hueStart ? 'score' : undef,
+		$hueStart,
+		$hueEnd,
+		$valueStart,
+		$valueEnd,
+		$supp
+	);
+	
+	my $nodeID = 0;
+	print OUT toStringXML($tree, $options{'name'}, 0, \%attributeHash, \$nodeID, $supp);
+	print OUT dataFooter();
+	print OUT htmlFooter();
+	close OUT;
+}
+
+
+################
+# Not exported #
+################
+
+
+sub addMember
+{
+	my ($node, $set, $member) = @_;
+	
+#	$member =~ s/,/\\,/g;
+#	$member =~ s/ / /g;
+#	$member =~ s/"/"/g;
+	
+	push @{$node->{'members'}[$set]}, $member;
+	$useMembers = 1;
+}
+
+sub argumentString
+{
+	my
+	(
+		$argumentName,
+		$useMagnitude,
+		$useName,
+		$number
+	) = @_;
+	
+	my $return;
+	
+	my $numberString;
+	
+	if ( $number > 0 )
+	{
+		$numberString = "_$number";
+	}
+	
+	if ( $number > 1 )
+	{
+		$return .= '[';
+	}
+	
+	$return .= "$argumentName$numberString";
+	
+	if ( $useMagnitude )
+	{
+		$return .= "[:$argumentNames{'magnitude'}$numberString]";
+	}
+	
+	if ( $useName )
+	{
+		$return .= "[,$argumentNames{'name'}$numberString]";
+	}
+	
+	if ( $number > 1 )
+	{
+		$return .= ']';
+	}
+	
+	return $return;
+}
+
+sub checkTaxonomy
+{
+	if ( ! @taxParents )
+	{
+		die 'Taxonomy not loaded. "loadTaxonomy()" must be called first.';
+	}
+}
+
+sub dataFooter
+{
+	return indent(2) . "</krona>\n";
+}
+
+sub dataHeader
+{
+	my
+	(
+		$magName,
+		$attributes,
+		$attributeDisplayNames,
+		$datasetNames,
+		$assignedName,
+		$summaryName,
+		$hueName,
+		$hueStart,
+		$hueEnd,
+		$valueStart,
+		$valueEnd,
+		$supp
+	) = @_;
+	
+	my $header =
+	indent(2) . '<krona collapse="' . ($options{'collapse'} ? 'true' : 'false') .
+	'" key="' . ($options{'key'} ? 'true' : 'false') . "\">\n" .
+	indent(3) . "<attributes magnitude=\"$magName\">\n";
+	
+	# members
+	#
+	my $assignedText;
+	my $summaryText;
+	#
+	if ( $assignedName && $summaryName && $useMembers )
+	{
+		my $memberTag = $supp ? 'data' : 'list';
+		my $suppDir = basename($options{'out'}) . $suppDirSuffix;
+		my $enableText = $supp ? " enable=\"$suppDir/$suppEnableFile\"" : '';
+		$header .= indent(4) . "<$memberTag$enableText>members</$memberTag>\n";
+		$assignedText = " ${memberTag}Node=\"members\"";
+		$summaryText = " ${memberTag}\All=\"members\"";
+		
+		if ( $options{'postUrl'} )
+		{
+			$assignedText .= " postUrl=\"$options{'postUrl'}\" postVar=\"queries\"";
+			$summaryText .= " postUrl=\"$options{'postUrl'}\" postVar=\"queries\"";
+		}
+	}
+	
+	# attributes
+	#
+	for ( my $i = 0; $i < @$attributes; $i++ )
+	{
+		my $attributeText;
+		my $name = $$attributes[$i];
+		
+		if ( $$attributeDisplayNames[$i] )
+		{
+			$attributeText .= " display=\"$$attributeDisplayNames[$i]\"";
+		}
+		
+		if ( $name eq 'count' )
+		{
+			# attach to list of members as summary of children
+			
+			$attributeText .= $summaryText;
+		}
+		elsif ( $name eq 'unassigned' )
+		{
+			# attach to list of members as node list
+			
+			$attributeText .= $assignedText;
+		}
+		elsif ( $name eq 'taxon' )
+		{
+			$attributeText .= " hrefBase=\"$taxonomyHrefBase\" target=\"taxonomy\"";
+		}
+		elsif ( $name eq 'ec' )
+		{
+			$attributeText .= " hrefBase=\"$ecHrefBase\" target=\"ec\"";
+		}
+		
+		if
+		(
+			$name eq 'taxon' ||
+			$name eq 'ec' ||
+			$name eq 'rank'
+		)
+		{
+			$attributeText .= ' mono="true"';
+		}
+		
+		$header .= indent(4) . "<attribute$attributeText>$$attributes[$i]</attribute>\n";
+	}
+	
+	$header .= indent(3) . "</attributes>\n";
+	
+	if ( @$datasetNames )
+	{
+		$header .= indent(3) . "<datasets>\n";
+		
+		foreach my $dataset ( @$datasetNames )
+		{
+			$dataset =~ s/</</g;
+			$dataset =~ s/>/>/g;
+			
+			$header .= indent(4) . "<dataset>$dataset</dataset>\n";
+		}
+		
+		$header .= indent(3) . "</datasets>\n";
+	}
+	
+	# hue
+	#
+	if ( defined $hueName )
+	{
+		my $colorDefault = $options{'color'} ? 'true' : 'false';
+		
+		$header .=
+			indent(3) . "<color attribute=\"$hueName\" " .
+			"hueStart=\"$hueStart\" hueEnd=\"$hueEnd\" " .
+			"valueStart=\"$valueStart\" valueEnd=\"$valueEnd\" " .
+			"default=\"$colorDefault\" " .
+			"></color>\n";
+	}
+	
+	return $header;
+}
+
+sub ecLink
+{
+	my ($ec) = @_;
+	
+	my $path = $ec;
+	
+	my $count = ($path =~ s/\./\//g);
+	
+	if ( $count == 3 )
+	{
+		$path .= ".html";
+	}
+	
+	return $path;
+}
+
+sub ecText
+{
+	my ($ec) = @_;
+	
+	return "EC $ec";
+}
+
+sub indent
+{
+	my ($depth) = @_;
+	
+	return ' ' x $depth;
+}
+
+sub printHangingIndent
+{
+	my ($header, $text, $tab) = @_;
+	
+	my @words = split /\s+/, $text;
+	
+	my $col;
+	
+	if ( $header )
+	{
+		print $header, ' ' x ($tab - (length $header) - 1);
+		$col = $tab;
+	}
+	else
+	{
+		my $word = shift @words;
+		print $word;
+		$col = length $word;
+	}
+	
+	foreach my $word ( @words )
+	{
+		my $wordLength = length $word;
+		
+		if ( $col + $wordLength + 1 >= $columns )
+		{
+			print "\n", ' ' x $tab, $word;
+			$col = $tab + $wordLength;
+		}
+		else
+		{
+			print " $word";
+			$col += $wordLength + 1;
+		}
+	}
+	
+	print "\n";
+}
+
+sub setInternalValues
+{
+	my ($node) = @_;
+	
+	my @magnitudes;
+	my @scoreTotals;
+	my @scoreCounts;
+	
+	if ( defined $node->{'children'} )
+	{
+		foreach my $child (values %{$node->{'children'}})
+		{
+			setInternalValues($child);
+			
+			for ( my $i = 0; $i < @{$child->{'magnitude'}}; $i++ )
+			{
+				if ( ! defined $node->{'magnitude'}[$i] )
+				{
+					$magnitudes[$i] += $child->{'magnitude'}[$i];
+				}
+				
+				if ( ! defined $node->{'scoreTotal'}[$i] )
+				{
+					$scoreTotals[$i] += $child->{'scoreTotal'}[$i];
+				}
+				
+				if ( ! defined $node->{'scoreCount'}[$i] )
+				{
+					$scoreCounts[$i] += $child->{'scoreCount'}[$i];
+				}
+			}
+		}
+	}
+	
+	for ( my $i = 0; $i < @{$node->{'count'}}; $i++ )
+	{
+		if ( ! defined $node->{'magnitude'}[$i] )
+		{
+			$node->{'magnitude'}[$i] = $magnitudes[$i];
+		}
+		
+		if ( ! defined $node->{'scoreTotal'}[$i] )
+		{
+			$node->{'scoreTotal'}[$i] = $scoreTotals[$i];
+		}
+		
+		if ( ! defined $node->{'scoreCount'}[$i] )
+		{
+			$node->{'scoreCount'}[$i] = $scoreCounts[$i];
+		}
+	}
+}
+
+sub setScores
+{
+	my ($node) = @_;
+	
+	my $min;
+	my $max;
+	
+	if ( defined $node->{'scoreCount'} )
+	{
+		$node->{'score'} = ();
+		
+		for ( my $i = 0; $i < @{$node->{'scoreCount'}}; $i++ )
+		{
+			my $score;
+			
+			if ( ${$node->{'scoreCount'}}[$i] )
+			{
+				$score =
+					${$node->{'scoreTotal'}}[$i] /
+					${$node->{'scoreCount'}}[$i];
+				
+				if ( $options{'logScore'} )
+				{
+					if ( $score > 0 )
+					{
+						$score = (log $score) / log 10;
+					}
+					else
+					{
+						$score = $minEVal;
+					}
+				}
+				
+				if ( ! defined $min || $score < $min )
+				{
+					$min = $score;
+				}
+				
+				if ( ! defined $max || $score > $max )
+				{
+					$max = $score;
+				}
+			}
+			else
+			{
+				$score = 0;
+			}
+			
+			${$node->{'score'}}[$i] = sprintf("%g", $score);
+		}
+	}
+	
+	if ( defined $node->{'children'} )
+	{
+		foreach my $child (keys %{$node->{'children'}})
+		{
+			my ($childMin, $childMax) =
+				setScores($node->{'children'}{$child});
+			
+			if ( ! defined $min || $childMin < $min )
+			{
+				$min = $childMin;
+			}
+			
+			if ( ! defined $max || $childMax > $max )
+			{
+				$max = $childMax;
+			}
+		}
+	}
+	
+	return ($min, $max);
+}
+
+sub slurp
+{
+	my ($fileName) = @_;
+	
+	local $/;
+	open FILE, $fileName or die "Can't read file '$fileName' [$!]\n";
+	my $file = <FILE>;
+	close (FILE);
+	return $file;
+}
+
+sub taxonLink
+{
+	my ($taxID) = @_;
+	
+	return $taxID;
+}
+
+sub toStringXML
+{
+	my ($node, $name, $depth, $attributeHash, $nodeIDRef, $supp) = @_;
+	
+	my $string;
+	my $href;
+	
+	if ( $node->{'href'} )
+	{
+		$href = " href=\"$node->{'href'}\"";
+	}
+	
+	$string = indent($depth) . "<node name=\"$name\"$href>\n";
+	
+	foreach my $key ( keys %$node )
+	{
+		if
+		(
+			$key ne 'children' &&
+			$key ne 'scoreCount' &&
+			$key ne 'scoreTotal' &&
+			$key ne 'href' &&
+			( keys %{$node->{'children'}} || ($key ne 'unassigned' && $key ne 'magnitudeUnassigned') ) &&
+			( $key eq 'members' || defined $$attributeHash{$key} )
+		)
+		{
+			$string .= indent($depth + 1) . "<$key>";
+			
+			my $i = 0;
+			
+			foreach my $value ( @{$node->{$key}} )
+			{
+				if ( $key eq 'members' )
+				{
+					if ( $supp )
+					{
+						if ( defined $value && @$value > 0 )
+						{
+							my $file = "node$$nodeIDRef.members.$i.js";
+							
+							$string .= "<val>$file</val>";
+							
+							open SUPP, ">$options{'out'}$suppDirSuffix/$file" or die;
+							
+							print SUPP "data('";
+							foreach my $member ( @$value )
+							{
+								print SUPP "$member\\n\\\n";
+							}
+							print SUPP "')";
+							
+							close SUPP;
+						}
+						else
+						{
+							$string .= "<val></val>";
+						}
+					}
+					else
+					{
+						$string .= "\n" . indent($depth + 2) . "<vals>";
+						
+						foreach my $member ( @$value )
+						{
+							$member =~ s/</</g;
+							$member =~ s/>/>/g;
+							
+							$string .= "<val>$member</val>";
+						}
+						
+						$string .= "</vals>";
+					}
+				}
+				else
+				{
+					my $href;
+					
+					if ( $key eq 'taxon' )
+					{
+						$href = ' href="' . taxonLink($value) . '"';
+					}
+					elsif ( $key eq 'ec' )
+					{
+						$href = ' href="' . ecLink($value) . '"';
+						$value = ecText($value);
+					}
+					
+					$value =~ s/</</g;
+					$value =~ s/>/>/g;
+					
+					$string .= "<val$href>$value</val>";
+				}
+				
+				$i++;
+			}
+			
+			if ( $key eq 'members' )
+			{
+				$string .= "\n" . indent($depth + 1);
+			}
+			
+			$string .= "</$key>\n";
+		}
+	}
+	
+	$$nodeIDRef++;
+	
+	if ( defined $node->{'children'} && ( ! $options{'depth'} || $depth < $options{'depth'} ) )
+	{
+		foreach my $child (keys %{$node->{'children'}})
+		{
+			$string .= toStringXML($node->{'children'}{$child}, $child, $depth + 1, $attributeHash, $nodeIDRef, $supp);
+		}
+	}
+	
+#	print "$string\n";
+	return $string . indent($depth) . "</node>\n";
+}
+
+sub validateOptions
+{
+	if ( defined $options{'factor'} && $options{'factor'} < 1 )
+	{
+		my $factor = getOptionString('factor');
+		ktDie("E-value factor ($factor) must be at least 1.");
+	}
+	
+	if ( $options{'percentIdentity'} && $options{'bitScore'} )
+	{
+		my $pi = getOptionString('percentIdentity');
+		my $bs = getOptionString('bitScore');
+		
+		ktDie("Cannot use $bs and $pi together.");
+	}
+}
+
+
+1;
diff --git a/KronaTools/scripts/ClassifyBLAST.pl b/KronaTools/scripts/ClassifyBLAST.pl
new file mode 100755
index 0000000..082072a
--- /dev/null
+++ b/KronaTools/scripts/ClassifyBLAST.pl
@@ -0,0 +1,141 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+my @options =
+qw(
+	out
+	threshold
+	random
+	percentIdentity
+	bitScore
+	summarize
+	factor
+);
+
+setOption('out', 'blast.taxonomy.tab');
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+'Assigns each query in tabular BLAST results to an NCBI taxonomy ID. If the
+results contain comment lines, queries with no hits will be included in the
+output (with taxonomy IDs of -1 for consistency with MEGAN).',
+		$KronaTools::argumentNames{'blast'},
+		$KronaTools::argumentDescriptions{'blast'},
+		0,
+		0,
+		\@options
+	);
+	printHeader('Output');
+	printColumns
+	(
+		'Default:',
+		'<queryID> <taxID> <score>',
+		'Summarized (-s):',
+		'<count> <taxID> <score>'
+	);
+	print "\n";
+	printColumns
+	(
+		'   queryID',
+		'The query ID as it appears in the BLAST results.',
+		'   taxID',
+'The NCBI taxonomy ID the query was assigned to (or -1 if it has no hits).',
+		'   score',
+'The score of the assignment(s); by default, the average E-value of "best" hits
+(see -p, -b).',
+		'   count',
+		'The number of assignments.'
+	);
+	print "\n";
+	
+	exit 0;
+}
+
+# load taxonomy
+
+print "Loading taxonomy...\n";
+loadTaxonomy();
+
+my %taxIDs;
+my %scores;
+
+# parse BLAST results
+
+foreach my $fileName (@ARGV)
+{
+	print "Classifying $fileName...\n";
+	classifyBlast($fileName, \%taxIDs, \%scores);
+}
+
+printWarnings();
+
+my $outFile = getOption('out');
+
+print "Writing $outFile...\n";
+
+open OUT, ">$outFile" or die "Could not open $outFile for writing";
+
+my $scoreName = getScoreName();
+
+if ( getOption('summarize') )
+{
+	my %magnitudes;
+	my %totalScores;
+	
+	print OUT "#count\ttaxID\t$scoreName\n";
+	
+	foreach my $queryID ( keys %taxIDs )
+	{
+		$magnitudes{$taxIDs{$queryID}}++;
+		$totalScores{$taxIDs{$queryID}} += $scores{$queryID};
+	}
+	
+	foreach my $taxID ( sort {$a <=> $b} keys %magnitudes )
+	{
+		print OUT join "\t",
+		(
+			$magnitudes{$taxID},
+			$taxID,
+			$totalScores{$taxID} / $magnitudes{$taxID}
+		), "\n";
+	}
+}
+else
+{
+	print OUT "#queryID\ttaxID\t$scoreName\n";
+	
+	foreach my $queryID ( sort keys %taxIDs )
+	{
+		print OUT "$queryID\t$taxIDs{$queryID}\t$scores{$queryID}\n";
+	}
+}
+
+close OUT;
+
+my $options = getOption('summarize') ? ' -m 1' : '';
+my $outFile = getOption('out');
+
+print "\nTo import, run:\n   ktImportTaxonomy$options $outFile\n\n";
diff --git a/KronaTools/scripts/ClassifyBLAST_hash.pl b/KronaTools/scripts/ClassifyBLAST_hash.pl
new file mode 100755
index 0000000..9ca749c
--- /dev/null
+++ b/KronaTools/scripts/ClassifyBLAST_hash.pl
@@ -0,0 +1,232 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+# get the path of this script; dependencies are relative
+#
+my $scriptPath;
+BEGIN
+{
+	use Cwd 'abs_path';
+	abs_path($0) =~ /(.*)\//;
+	$scriptPath = $1;
+}
+use lib "$scriptPath/../lib";
+
+use Krona;
+
+my $totalMag;
+
+my @options =
+qw(
+	out
+	radius
+	verbose
+);
+
+setOption('out', 'blast.taxonomy.tab');
+setOption('radius', 0);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+ 	print '
+
+Description:
+   Infers taxonomic abundance from BLAST results.
+
+Usage:
+
+ktClassifyBLAST [options] \
+   blast_output_1[:magnitude_file_1] \
+   blast_output_2[:magnitude_file_2] \
+   ...
+
+Input:
+
+   blast_output      File containing BLAST results in tabular format ("Hit table
+                     (text)" when downloading from NCBI).  If running BLAST
+                     locally, subject IDs in the local database must contain GI
+                     numbers in "gi|12345" format.
+   
+   [magnitude_file]  Optional file listing query IDs with magnitudes, separated
+                     by tabs.  The can be used to account for read length or
+                     contig depth to obtain a more accurate representation of
+                     abundance.  By default, query sequences without specified
+                     magnitudes will be assigned a magnitude of 1.  Magnitude
+                     files for Newbler or Celera Assembler assemblies can be
+                     created with getContigMagnitudesNewbler.pl or
+                     getContigMagnitudesCA.pl
+
+';
+	printOptions(@options);
+	exit;
+}
+
+my %bestScores;
+my %lca;
+my %lcaMag;
+
+# load taxonomy
+
+print "Loading taxonomy...\n";
+loadTaxonomy();
+
+# parse BLAST results
+
+foreach my $input (@ARGV)
+{
+	my ($fileName, $magFile) = split /:/, $input;
+	
+	$fileName =~ /([^\/]+)\./;
+	
+	my %magnitudes;
+	
+	# load magnitudes
+	
+	if ( defined $magFile )
+	{
+		print "Loading magnitudes for $fileName...\n";
+		
+		open MAG, "<$magFile" or die $!;
+		
+		while ( my $line = <MAG> )
+		{
+			chomp $line;
+			my ( $id, $mag ) = split /\t/, $line;
+			$magnitudes{$id} = $mag;
+		}
+		
+		close MAG;
+	}
+	
+	print "Classifying $fileName...\n";
+	
+	open BLAST, "<$fileName";
+	
+	my $lastQueryID;
+	my $topScore;
+	my $taxID;
+	my $score;
+	
+	while ( my $line = <BLAST> )
+	{
+		if ( $line =~ /^#/ )
+		{
+			next;
+		}
+		
+		chomp $line;
+		
+		my
+		(
+			$queryID,
+			$hitID,
+			$identity,
+			$length,
+			$mismatches,
+			$gaps,
+			$queryStart,
+			$queryEnd,
+			$subjectStart,
+			$subjectEnd,
+			$eVal,
+			$bitScore
+		) = split /\t/, $line;
+		
+		$hitID =~ /gi\|(\d+)/;
+		my $gi = $1;
+		
+		my $bestScore = $bestScores{$queryID};
+		#print "$queryID\t$bestScore\n";
+		if
+		(
+			defined $gi &&
+			(
+				! defined $bestScore ||
+				$bitScore >= $bestScore - getOption('radius')
+			)
+		)
+		{
+			if
+			(
+				! defined $bestScore ||
+				$bitScore > $bestScore
+			)
+			{
+				$bestScores{$queryID} = $bitScore
+			}
+			
+			my $taxID = getTaxID($gi);
+			
+			if ( defined $lca{$queryID} )
+			{
+				$lca{$queryID} = lowestCommonAncestor($lca{$queryID}, $taxID);
+			}
+			else
+			{
+				$lca{$queryID} = $taxID;
+			}
+			
+			if ( defined $magnitudes{$lastQueryID} )
+			{
+				$lcaMag{$queryID} = $magnitudes{$queryID};
+			}
+			else
+			{
+				$lcaMag{$queryID} = 1;
+			}
+			
+		}
+	}
+}
+
+my %totalMagnitudes;
+my %totalScores;
+my %totalCounts;
+
+print "Computing taxon totals...\n";
+
+foreach my $query ( keys %lca )
+{
+	# add the chosen hit from the last queryID
+	
+	my $taxID = $lca{$query};
+	
+	if ( getOption('verbose') )
+	{
+		print "$query:\ttaxID=$taxID\tmag=$lcaMag{$query}\tscore=$bestScores{$query}\n";
+	}
+	
+	#add($set, \%tree, $taxID, $magnitude, $score);
+	
+	$totalMagnitudes{$taxID} += $lcaMag{$query};
+	$totalScores{$taxID} += $bestScores{$query};
+	$totalCounts{$taxID}++;
+}
+
+my $outFile = getOption('out');
+
+print "Writing $outFile...\n";
+
+open OUT, ">$outFile" or die "Could not open $outFile for writing";
+
+foreach my $taxID ( keys %totalMagnitudes )
+{
+	my $score = $totalScores{$taxID} / $totalCounts{$taxID};
+	
+	print OUT "$taxID\t$totalMagnitudes{$taxID}\t$score\n";
+}
+
+close OUT;
diff --git a/KronaTools/scripts/GetContigMagnitudes.pl b/KronaTools/scripts/GetContigMagnitudes.pl
new file mode 100755
index 0000000..d56b409
--- /dev/null
+++ b/KronaTools/scripts/GetContigMagnitudes.pl
@@ -0,0 +1,55 @@
+#!/usr/bin/env perl
+
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+if ( @ARGV < 2 )
+{
+	my $scriptName = getScriptName();
+	
+	printHeader("KronaTools $KronaTools::version - $scriptName");
+	print
+'Takes an ACE assembly file and writes a magnitude file for use with import
+scripts.  The magnitude of each contig will be the total number of reads
+assigned to it.
+
+';
+	printHeader('Usage');
+	print
+"$scriptName <assembly.ace> <output>
+
+";
+	exit;
+}
+
+my ($ace, $output) = @ARGV;
+
+
+open ACE, "<$ace" or die $!;
+open OUT, ">$output" or die $!;
+
+while ( my $line = <ACE> )
+{
+	if ( $line =~ /^CO\s+([^\s]+)\s+\d+\s+(\d+)/ )
+	{
+		print OUT "$1\t$2\n";
+	}
+}
+
+close OUT;
+close ACE;
diff --git a/KronaTools/scripts/GetContigMagnitudesCONTIG.pl b/KronaTools/scripts/GetContigMagnitudesCONTIG.pl
new file mode 100755
index 0000000..a6cd803
--- /dev/null
+++ b/KronaTools/scripts/GetContigMagnitudesCONTIG.pl
@@ -0,0 +1,59 @@
+#!/usr/bin/env perl
+
+# Copyright 2011 Brian Ondov
+# 
+# This file is part of Radiant.
+# 
+# Radiant is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# Radiant is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with Radiant.  If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+
+
+if ( @ARGV < 2 )
+{
+	print '
+
+ktGetContigMagnitudesCONTIG <assembly.contig> <output>
+
+Writes a magnitude file for use with import scripts.  The magnitude of each
+contig will be the total number of reads assigned to it.
+
+';
+	exit;
+}
+
+my ($contig, $output) = @ARGV;
+
+
+open CONTIG, "<$newblerFolder/454ContigGraph.txt" or die $!;
+open OUT, ">$output" or die $!;
+
+while ( my $line = <CONTIG> )
+{
+	if ( $line =~ /^C/ )
+	{
+		last;
+	}
+	else
+	{
+		my @values = split /\t/, $line;
+		
+		my $magnitude = $values[2] * $values[3];
+		print OUT "$values[1]\t$magnitude\n";
+	}
+}
+
+close OUT;
+close CONTIG;
+
diff --git a/KronaTools/scripts/GetContigMagnitudesNewbler.pl b/KronaTools/scripts/GetContigMagnitudesNewbler.pl
new file mode 100755
index 0000000..64dc159
--- /dev/null
+++ b/KronaTools/scripts/GetContigMagnitudesNewbler.pl
@@ -0,0 +1,60 @@
+#!/usr/bin/env perl
+
+# Copyright 2011 Brian Ondov
+# 
+# This file is part of Radiant.
+# 
+# Radiant is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# Radiant is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with Radiant.  If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+
+
+if ( @ARGV < 2 )
+{
+	print '
+
+getContigMagnitudesNewbler.pl <assembly_folder> <output>
+
+Writes a magnitude file for use with import scripts.  The magnitude of each
+contig will be the total number of bases assigned to it (also equal to
+depth * length).
+
+';
+	exit;
+}
+
+my ($newblerFolder, $output) = @ARGV;
+
+
+open INFO, "<$newblerFolder/454ContigGraph.txt" or die $!;
+open OUT, ">$output" or die $!;
+
+while ( my $line = <INFO> )
+{
+	if ( $line =~ /^C/ )
+	{
+		last;
+	}
+	else
+	{
+		my @values = split /\t/, $line;
+		
+		my $magnitude = $values[2] * $values[3];
+		print OUT "$values[1]\t$magnitude\n";
+	}
+}
+
+close OUT;
+close INFO;
+
diff --git a/KronaTools/scripts/GetLCA.pl b/KronaTools/scripts/GetLCA.pl
new file mode 100755
index 0000000..ac0b848
--- /dev/null
+++ b/KronaTools/scripts/GetLCA.pl
@@ -0,0 +1,117 @@
+#!/usr/bin/env perl
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+use Getopt::Long;
+
+my $help;
+my $stream;
+my $tax;
+
+GetOptions
+(
+	'h' => \$help,
+	'help' => \$help,
+	's' => \$stream,
+	'tax=s' => \$tax
+);
+
+if ( defined $tax )
+{
+	setOption('taxonomy', $tax);
+}
+
+if ( $help )
+{
+	print '
+Description:
+
+   Computes the lowest common ancestor for accessions or taxonomy IDs (as
+   arguments or from <stdin>). If an input is a number, it is assumed to be a
+   taxonomy ID; otherwise it will be considered an accession or sequence ID
+   containing an accession in the fourth field of pipe notation (e.g.
+   "gi|12345|xx|ABC123.1|", ignoring fasta/fastq tag markers [>,@]). If using
+   <stdin>, the LCA can be computed for the first fields of all input lines
+   (default), or per input line, separated by whitespace (see -s).
+
+Usage:
+
+   ktGetLCA [options] [acc/tax_ID ...] [< acc/taxID_list] > LCA
+
+Options:
+
+   -s  Streaming mode. Each line is expected to be a whitespace-separated list 
+       of inputs for a single lowest common ancestor computation. Taxonomy will
+       be preloaded, allowing for faster computation after a small upfront time.
+
+';
+	exit;
+}
+
+if ( $stream )
+{
+	loadTaxonomy();
+}
+
+my $stdin;
+
+if ( @ARGV == 0 || $stream )
+{
+	$stdin = 1;
+}
+
+my @taxIDs;
+
+while ( my $in = $stdin ? <STDIN> : shift @ARGV )
+{
+	chomp $in;
+	
+	if ( $stream )
+	{
+		if ( $in eq "" )
+		{
+			print "\n";
+			next;
+		}
+		
+		my @taxIDs;
+		
+		foreach my $id (split /\s+/, $in)
+		{
+			my $taxID = getTaxIDFromAcc(getAccFromSeqID($id));
+			
+			if ( $taxID != 0 )
+			{
+				push @taxIDs, $taxID;
+			}
+		}
+		
+		my $lca = taxLowestCommonAncestor(@taxIDs);
+		print "$lca\n";
+	}
+	else
+	{
+		my $taxID = getTaxIDFromAcc(getAccFromSeqID($in));
+		
+		if ( $taxID != 0 )
+		{
+			push @taxIDs, $taxID;
+		}
+	}
+}
+
+if ( ! $stream )
+{
+	my $lca = taxLowestCommonAncestor(@taxIDs);
+	print "$lca\n";
+}
+
+printWarnings();
diff --git a/KronaTools/scripts/GetLibPath.pl b/KronaTools/scripts/GetLibPath.pl
new file mode 100755
index 0000000..8b60d6a
--- /dev/null
+++ b/KronaTools/scripts/GetLibPath.pl
@@ -0,0 +1,13 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+use Cwd 'abs_path';
+abs_path($0) =~ /(.*)\//;
+print abs_path("$1/../lib");
diff --git a/KronaTools/scripts/GetTaxIDFromAcc.pl b/KronaTools/scripts/GetTaxIDFromAcc.pl
new file mode 100755
index 0000000..3569180
--- /dev/null
+++ b/KronaTools/scripts/GetTaxIDFromAcc.pl
@@ -0,0 +1,112 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+use Getopt::Long;
+
+my $help;
+my $prepend;
+my $append;
+my $tax;
+
+GetOptions
+(
+	'h' => \$help,
+	'help' => \$help,
+	'p' => \$prepend,
+	'a' => \$append,
+	'tax=s' => \$tax
+);
+
+if ( defined $tax )
+{
+	setOption('taxonomy', $tax);
+}
+
+if ( $help )
+{
+	print '
+Description:
+
+   Translates accessions (from arguments or <stdin>) to NCBI taxonomy IDs. The
+   accession can be bare or in the fourth field of pipe notation (e.g.
+   "gi|12345|xx|ABC123.1|", ignoring fasta tag markers [">"]). Inputs that are
+   bare numbers will be assumed to be taxonomy IDs already and preserved.
+   Accessions with no taxonomy IDs in the database will return 0.
+
+Usage:
+
+   ktGetTaxIDFromAcc [options] [acc1 acc2 ...] [< acc_list] > tax_ID_list
+
+   Command line example:
+   
+      ktGetTaxIDFromAcc A00001.1 A00002.1
+
+   Fasta tag example:
+
+      grep ">" sequence
+
+Options:
+
+   -p  Prepend tax IDs to the original lines (separated by tabs).
+  
+   -a  Append tax IDs to the original lines (separated by tabs).
+
+';
+	exit;
+}
+
+if ( $prepend && $append )
+{
+	ktWarn('Both -p and -a specified. Only -a will be used.');
+	$prepend = 0;
+}
+
+my $stdin;
+
+if ( @ARGV == 0 )
+{
+	$stdin = 1;
+}
+
+while ( my $in = $stdin ? <STDIN> : shift @ARGV )
+{
+	chomp $in;
+	
+	if ( $in eq "" )
+	{
+		print "\n";
+		next;
+	}
+	
+	if ( $append )
+	{
+		print "$in\t";
+	}
+	
+	print getTaxIDFromAcc(getAccFromSeqID($in));
+	
+	if ( $prepend )
+	{
+		print "\t$in";
+	}
+	
+	print "\n";
+}
+
+printWarnings();
diff --git a/KronaTools/scripts/GetTaxInfo.pl b/KronaTools/scripts/GetTaxInfo.pl
new file mode 100755
index 0000000..a8271f2
--- /dev/null
+++ b/KronaTools/scripts/GetTaxInfo.pl
@@ -0,0 +1,86 @@
+#!/usr/bin/env perl
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+use Getopt::Long;
+
+my $help;
+my $totalMag;
+my $prepend;
+my $append;
+my $tax;
+
+GetOptions
+(
+	'h' => \$help,
+	'help' => \$help,
+	'tax=s' => \$tax
+);
+
+if ( defined $tax )
+{
+	setOption('taxonomy', $tax);
+}
+
+if ( $help )
+{
+	print '
+Description:
+
+   Retrieves taxonomy information for accessions or taxonomy IDs (as arguments
+   or the first field of <stdin>, separated by whitespace). If the input is a
+   number, it is assumed to be a taxonomy ID; otherwise it will be considered an
+   accession or sequence ID containing an accession in the fourth field of pipe
+   notation (e.g. "gi|12345|xx|ABC123.1|", ignoring fasta/fastq tag markers
+   [>,@]). If taxonomy information was not found for a given input line, the
+   output line will be only the taxonomy ID, which will be 0 if it was
+   looked up from an accession but not found.
+
+Usage:
+
+   ktGetTaxInfo [IDs ...] [< ID_list] > tax_info
+
+   Command line example:
+
+      ktGetTaxInfo A00001.1 "gi|2|emb|A00002.1|" 9606
+
+   Fasta tag example:
+
+      grep ">" sequence.fasta | ktGetTaxInfo
+
+';
+	exit;
+}
+
+print "#taxID\tdepth\tparent\trank\tname\n";
+
+my $stdin;
+
+if ( @ARGV == 0 )
+{
+	$stdin = 1;
+}
+
+while ( my $in = $stdin ? <STDIN> : shift @ARGV )
+{
+	chomp $in;
+	
+	if ( $in eq "" )
+	{
+		print "\n";
+		next;
+	}
+	
+	print join "\t", getTaxInfo(getTaxIDFromAcc(getAccFromSeqID($in)));
+	print "\n";
+}
+
+printWarnings();
diff --git a/KronaTools/scripts/ImportAmphora.pl b/KronaTools/scripts/ImportAmphora.pl
new file mode 100755
index 0000000..1ba3718
--- /dev/null
+++ b/KronaTools/scripts/ImportAmphora.pl
@@ -0,0 +1,248 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+my $AMPHORA_MIN_CONFIDENCE = 0.15;
+my %TAXONOMIC_ORDERING = ( 
+		"no rank" => 0,
+		"domain" => 1,
+		"superkingdom" => 1.9,
+		"kingdom" => 2,
+		"subkingdom" => 2.5,
+		"superphylum" => 2.9,
+		"phylum" => 3,
+		"subphylum" => 3.5,
+		"superclass" => 3.9,
+		"class" => 4,
+		"subclass" => 4.5,
+		"superorder" => 4.9,
+		"order" => 5,
+		"suborder" => 5.5,
+		"superfamily" => 5.9,
+		"family" => 6,
+		"subfamily" => 6.5,
+		"supergenus" => 6.9,
+		"genus" => 7.0,
+		"subgenus" => 7.5,
+		"superspecies" => 7.9,
+		"species" => 8.5,
+		"subspecies" => 9,
+);
+
+my $totalMag;
+
+setOption('out', 'report.krona.html');
+setOption('name', 'Root');
+
+my @options =
+qw(
+	out
+	include
+	combine
+	hueBad
+	hueGood
+	local
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+		'Infers taxonomic abundance from Amphora results.',
+		'amphora_output',
+		'Amphora output.',
+		1,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+
+# load taxonomy
+
+print "Loading taxonomy...\n";
+loadTaxonomy();
+
+# parse BLAST results
+
+my $set = 0;
+my @datasetNames;
+my $zeroEVal;
+my $useMag;
+
+foreach my $input (@ARGV)
+{
+	my $totalMagnitude;
+	
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $1;
+	}
+	
+	my %magnitudes;
+	
+	# load magnitudes
+	
+	if ( defined $magFile )
+	{
+		print "   Loading magnitudes from $magFile...\n";
+		loadMagnitudes($magFile, \%magnitudes);
+		$useMag = 1;
+	}
+	
+	print "Importing $fileName...\n";
+	 
+	open BLAST, "<$fileName";
+        my $annotFile = $magFile;
+        #print "$annotFile\n";
+        $annotFile =~ s/contig.cvg/annots/;
+        #print "$annotFile\n";
+        $annotFile = getOption('out') . '.ann';
+        open ANNOTS, ">$annotFile" or die $!;
+
+	my $topScore;
+	my $ties;
+        my $taxID = undef;
+        my $currCtg = undef;
+	my $magnitude = 0;
+        my %bestTaxa;
+        my %bestScores;
+
+        print ANNOTS "contigID\tclassID\n";
+	while ( 1 )
+	{
+		my $line = <BLAST>;
+		
+		chomp $line;
+                #print "$line";
+		my
+		(
+                        $contigID,
+			$taxID,
+                        $taxLevel,
+			$taxaName,
+			$score
+
+		) = split /\t/, $line; #split /\t/, $line;
+                if (!defined($contigID) || (defined($currCtg) && !($currCtg eq $contigID))) {
+                   my $magnitude = 1;
+                   if (defined($magnitudes{$currCtg})) {
+                      $magnitude = $magnitudes{$currCtg}
+                    }
+                    # pick the best level to use
+                    my $bestTaxon;
+                    my $bestName;
+                    my $printed = 0;
+
+                    foreach my $taxa (keys %bestScores) {
+                       #print "$taxa\n";
+                       if ($printed == 0 && $taxa eq "class")
+                       {
+                           $printed = 1;
+                           print ANNOTS "$currCtg\t$bestTaxa{$taxa}\n";
+                       }
+
+                       if ($bestScores{$taxa} > $AMPHORA_MIN_CONFIDENCE) {
+                          if (!defined($bestTaxon)) {
+                             $bestTaxon = $bestTaxa{$taxa};
+                             $bestName = $taxa;
+                          } else {
+                             if ($TAXONOMIC_ORDERING{$bestName} < $TAXONOMIC_ORDERING{$taxa}) {
+                                   $bestTaxon = $bestTaxa{$taxa};
+                                   $bestName = $taxa;
+                        
+                             }
+                          }
+                       }
+                    }
+                    print "$currCtg\t$bestTaxon\n";
+                    addByTaxID($tree, $set, $bestTaxon, $currCtg, $magnitude, $bestScores{$bestName});
+                    $totalMagnitude += $magnitude;
+                    %bestScores = ();
+                    %bestTaxa = ();
+                }
+
+                if ( ! defined $taxID )
+                {
+                        last; # EOF
+                }
+                if ( defined $taxID )
+		{
+                        if (!defined($bestScores{$taxLevel}) || $bestScores{$taxLevel} < $score) {
+                           $bestScores{$taxLevel} = $score;
+                           $bestTaxa{$taxLevel} = $taxID;
+                        }
+                        $currCtg = $contigID; 
+		}
+	}
+	
+	if ( getOption('include') && $totalMagnitude )
+	{
+		$$tree{'magnitude'}[$set] = $totalMagnitude; # TODO: this should be changed to an add()
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+}
+
+if ( $zeroEVal )
+{
+	print "\nWARNING: Couldn't take log for e-values of 0.  Used 1e-413.\n\n";
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'count',
+	'unassigned',
+	'taxon',
+	'rank',
+	'score',
+);
+
+my @attributeDisplayNames =
+(
+	$useMag ? 'Total' : undef,
+	'Count',
+	'Unassigned',
+	'Taxon',
+	'Rank',
+	'Confidence',
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('hueBad'),
+	getOption('hueGood')
+);
diff --git a/KronaTools/scripts/ImportBLAST.pl b/KronaTools/scripts/ImportBLAST.pl
new file mode 100755
index 0000000..8753de2
--- /dev/null
+++ b/KronaTools/scripts/ImportBLAST.pl
@@ -0,0 +1,175 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+# defaults
+#
+setOption('out', 'blast.krona.html');
+setOption('name', 'Root');
+
+my @options =
+qw(
+	out
+	name
+	threshold
+	include
+	random
+	percentIdentity
+	bitScore
+	combine
+	depth
+	noRank
+	hueBad
+	hueGood
+	url
+	postUrl
+	taxonomy
+	factor
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+"Creates a Krona chart of taxonomic classifications computed from tabular BLAST
+results.",
+		$KronaTools::argumentNames{'blast'},
+		$KronaTools::argumentDescriptions{'blast'},
+		1,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+
+# load taxonomy
+
+print "Loading taxonomy...\n";
+loadTaxonomy();
+
+# parse BLAST results
+
+my $set = 0;
+my @datasetNames;
+my $useMag;
+
+foreach my $input (@ARGV)
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	my %magnitudes;
+	my %taxIDs;
+	my %scores;
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $fileName...\n";
+	
+	# load magnitudes
+	
+	if ( defined $magFile )
+	{
+		print "   Loading magnitudes from $magFile...\n";
+		loadMagnitudes($magFile, \%magnitudes);
+		$useMag = 1;
+	}
+	
+	print "   Classifying BLAST results...\n";
+	classifyBlast($fileName, \%taxIDs, \%scores);
+	
+	print "   Computing tree...\n";
+	
+	foreach my $queryID ( keys %taxIDs )
+	{
+		my $taxID = $taxIDs{$queryID};
+		
+		if ( $taxID == -1 )
+		{
+			if ( getOption('include') )
+			{
+				$taxID = 0;
+			}
+			else
+			{
+				next;
+			}
+		}
+		
+		addByTaxID
+		(
+			$tree,
+			$set,
+			$taxID,
+			$queryID,
+			$magnitudes{$queryID},
+			$scores{$queryID}
+		);
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'magnitudeUnassigned',
+	'count',
+	'unassigned',
+	'taxon',
+	'rank',
+	'score'
+);
+
+my @attributeDisplayNames =
+(
+	$useMag ? 'Magnitude' : undef,
+	$useMag ? 'Unassigned magnitude' : undef,
+	'Count',
+	'Unassigned',
+	'Tax ID',
+	'Rank',
+	getScoreName(),
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('bitScore') || getOption('percentIdentity') ?
+		getOption('hueBad') : 
+		getOption('hueGood'),
+	getOption('bitScore') || getOption('percentIdentity') ?
+		getOption('hueGood') :
+		getOption('hueBad')
+);
diff --git a/KronaTools/scripts/ImportDiskUsage.pl b/KronaTools/scripts/ImportDiskUsage.pl
new file mode 100755
index 0000000..75d6090
--- /dev/null
+++ b/KronaTools/scripts/ImportDiskUsage.pl
@@ -0,0 +1,214 @@
+#!/usr/bin/env perl
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+my $otherName = '[Small files or folders]';
+
+setOption('out', 'du.krona.html');
+
+my @options =
+qw(
+	out
+	url
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	my $scriptName = getScriptName();
+	
+	printHeader("KronaTools $KronaTools::version - $scriptName");
+	print
+'Creates a Krona chart of disk usage of files and folders in the specified
+directory. Symbolic links and mount points within the directory are not
+followed. Small files or folders (that are less than 0.1% of the total size)
+will be grouped. The chart can be colored by log[10] of the number of days
+since each file or folder was modified.
+';
+	printHeader('Usage');
+	print
+"$scriptName [options] <dir>
+";
+	printOptions(@options);
+	exit;
+}
+
+my %all;
+my ($path) = @ARGV;
+my $time = time;
+
+$path = abs_path($path);
+
+my $name = basename($path);
+
+if ( $name ne '/' )
+{
+	$name .= '/';
+}
+
+setOption('name', $name);
+setOption('collapse', 0);
+setOption('color', 0);
+
+if ( ! -e $path )
+{
+	ktDie("\"$path\" does not exist.");
+}
+
+# First, get recursive sizes quickly with 'du'.  Then small directories don't
+# have to be scanned later when building the tree and getting file stats.
+#
+my %sizes;
+
+open DU, "du -aHkx '$path' 2> /dev/null |";
+#
+while ( <DU> )
+{
+	chomp;
+	my ($size, $file) = split /\t/;
+	$sizes{$file} = $size;
+}
+close DU;
+
+my $total = $sizes{$path};
+my $minSize = $total / 1000;
+
+my @units =
+qw(
+	Kb
+	Mb
+	Gb
+	Tb
+	Eb
+);
+
+my $unit = int((log $total / 10) / (log 2) / 10);
+my $unitSize = 2 ** ($unit * 10);
+
+add(\%all, abs_path($path), 1);
+
+my @attributeNames =
+(
+	'magnitude',
+	'age',
+	'score'
+);
+
+my @attributeDisplayNames =
+(
+	"Size ($units[$unit])",
+	'Age (days since modified)',
+	'Log(Age+1)'
+);
+
+my @datasetNames;
+
+writeTree
+(
+	\%all,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	300,
+	240
+);
+
+my $outFile = getOption('out');
+#system("open $outFile");
+
+sub add
+{
+	my $child;
+	my ($node, $path, $big) = @_;
+	
+	if ( $big && ! defined ${$node}{'children'} )
+	{
+		${$node}{'children'} = ();
+		${$node}{'href'} = 'file://localhost' . $path;
+	}
+	
+	my @stats = stat $path;
+	my $age = int(($time - $stats[9]) / 86400);
+	
+	if ( $age < 0 )
+	{
+		$age = 0;
+	}
+	
+	my $logAge = log ($age + 1) / log 10;
+	
+	${$node}{'magnitude'}[0] += $sizes{$path} / $unitSize;
+	
+	if
+	(
+		$big ||
+		! defined ${$node}{'scoreTotal'} ||
+		$logAge < ${$node}{'scoreTotal'}[0]
+	)
+	{
+		${$node}{'scoreTotal'}[0] = $logAge;
+		${$node}{'scoreCount'}[0] = 1;
+		${$node}{'age'}[0] = int($age);
+	}
+	
+	if ( $big && -d $path && (! -l $path) && opendir DIR, $path )
+	{
+		my @files = readdir DIR;
+		closedir DIR;
+		
+		if ( $path ne '/' )
+		{
+			$path .= '/';
+		}
+		
+		foreach my $file ( @files )
+		{
+			if ( $file eq '.' || $file eq '..' )
+			{
+				next;
+			}
+			
+			my $childName;
+			
+			my $childPath = $path . $file;
+			my $big;
+			
+			if ( $sizes{$childPath} > $minSize )
+			{
+				if ( -d $childPath )
+				{
+					$file .= '/';
+				}
+				
+				$childName = $file;
+				$big = 1; # tell add() that this child is big enough to show
+			}
+			else
+			{
+				$childName = $otherName; # group this child with others
+			}
+			
+			if ( ! defined ${$node}{'children'}{$childName} )
+			{
+				my %newHash = ();
+				${$node}{'children'}{$childName} = \%newHash;
+			}
+			
+			$child = ${$node}{'children'}{$childName};
+			
+			add($child, $childPath, $big);
+		}
+	}
+}
diff --git a/KronaTools/scripts/ImportEC.pl b/KronaTools/scripts/ImportEC.pl
new file mode 100755
index 0000000..0300706
--- /dev/null
+++ b/KronaTools/scripts/ImportEC.pl
@@ -0,0 +1,251 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('out', 'ec.krona.html');
+setOption('name', 'root');
+
+my @options =
+qw(
+	out
+	name
+	combine
+	queryCol
+	ecCol
+	scoreCol
+	magCol
+	include
+	depth
+	hueBad
+	hueGood
+	url
+	postUrl
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+		'Creates a Krona chart of abundances of EC (Enzyme Commission) numbers
+in tab-delimited files.',
+		'ec_numbers',
+		'Tab-delimited files with EC numbers and (optionally) query IDs,
+magnitudes and scores. By default, query IDs, EC numbers and scores will be
+taken from columns 1, 2 and 3, respectively (see -q, -e, -s, and -m).',
+		1,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+if ( optionsConflict('queryCol', 'ecCol', 'magCol', 'scoreCol') )
+{
+	ktWarn('Query column already in use; not reading query IDs.');
+	setOption('queryCol', undef);
+}
+
+if ( optionsConflict('scoreCol', 'ecCol', 'magCol') )
+{
+	ktWarn('Score column already in use; not reading scores.');
+	setOption('scoreCol', undef);
+}
+
+if ( optionsConflict('magCol', 'ecCol') )
+{
+	ktWarn('Magnitude column already in use; not reading magnitudes.');
+	setOption('magCol', undef);
+}
+
+my $tree = newTree();
+
+print "Loading EC names...\n";
+loadEC();
+
+my $set = 0;
+my @datasetNames;
+my $useScore = 1; # is score column present?
+my $eVal; # is score e-value (inferred by negative scores)?
+my $useMag = getOption('magCol'); # using magnitude values?
+
+foreach my $input (@ARGV)
+{
+	my ($file, $magFile, $name) = parseDataset($input);
+	
+	my %magnitudes;
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $file...\n";
+	
+	# load magnitudes
+	
+	if ( defined $magFile )
+	{
+		if ( getOption('queryCol') )
+		{
+			print "   Loading magnitudes from $magFile...\n";
+			loadMagnitudes($magFile, \%magnitudes);
+			$useMag = 1;
+		}
+		else
+		{
+			ktWarn("Query column not defined; not reading magnitudes from \"$magFile.\"");
+		}
+	}
+	
+	open IN, "<$file" or die "Couldn't open $file.";
+	
+	while ( my $line = <IN> )
+	{
+		my @fields = split /\t/, $line;
+		
+		my $queryID;
+		my $ec = $fields[getOption('ecCol') - 1];
+		my $magnitude;
+		my $score;
+		
+		if ( getOption('queryCol') )
+		{
+			$queryID = $fields[getOption('queryCol') - 1];
+		}
+		
+		if ( getOption('scoreCol') )
+		{
+			$score = $fields[getOption('scoreCol') - 1];
+		}
+		
+		if ( defined $queryID && defined $magnitudes{$queryID} )
+		{
+			$magnitude = $magnitudes{$queryID};
+		}
+		elsif ( defined getOption('magCol') )
+		{
+			$magnitude = $fields[getOption('magCol') - 1];
+		}
+		else
+		{
+			$magnitude = 1;
+		}
+		
+		$ec =~ s/^EC//; # remove 'EC' if present
+		
+		while ( $ec =~ s/\.-$// ) {}; # repeatedly remove trailing '.-'
+		
+		if ( $ec ne '' && $ec !~ /^[\d\.]+$/ )
+		{
+			ktWarn("$queryID: Bad EC ('$ec'); ignoring.");
+			$ec = '';
+		}
+		
+		if ( $ec || getOption('include') )
+		{
+			my @ecs;
+			
+			if ( $ec )
+			{
+				@ecs = split /\./, $ec;
+			}
+			
+			addByEC($tree, $set, \@ecs, $queryID, $magnitude, $score);
+		}
+		
+		if ( ! defined $score ) # all lines must have score to be used
+		{
+			$useScore = 0;
+		}
+		
+		if ( $score < 0 ) # score is probably e-value; flip colors
+		{
+			$eVal = 1;
+		}
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+	
+	close IN;
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'count',
+	'unassigned',
+	'ec',
+);
+
+my @attributeDisplayNames =
+(
+	$useMag ? 'Magnitude' : (getOption('queryCol') ? undef : 'Count'),
+	getOption('queryCol') ? 'Count' : undef,
+	'Unassigned',
+	'EC'
+);
+
+my @scoreArgs;
+
+if ( $useScore )
+{
+	push @attributeNames, 'score';
+	push @attributeDisplayNames, 'Avg. score';
+	
+	@scoreArgs =
+	(
+		$eVal ? getOption('hueGood') : getOption('hueBad'),
+		$eVal ? getOption('hueBad') : getOption('hueGood')
+	)
+}
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	@scoreArgs
+);
+
+sub optionsConflict
+{
+	my ($option, @others) = @_;
+	
+	if ( getOption($option) )
+	{
+		foreach my $other ( @others )
+		{
+			if ( getOption($option) == getOption($other) )
+			{
+				return 1;
+			}
+		}
+	}
+	
+	return 0;
+}
diff --git a/KronaTools/scripts/ImportFCP.pl b/KronaTools/scripts/ImportFCP.pl
new file mode 100755
index 0000000..59ef40e
--- /dev/null
+++ b/KronaTools/scripts/ImportFCP.pl
@@ -0,0 +1,138 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('out', 'fcp.krona.html');
+setOption('name', 'root');
+
+my @options =
+qw(
+	out
+	name
+	combine
+	depth
+	url
+	postUrl
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+'Creates a Krona chart based on the results of FCP (Fragment Classification
+Package).',
+		'fcp_output',
+'Results of running any FCP classification tool (except BLASTN.py, which only
+outputs raw BLAST results).',
+		1,
+		1,
+		\@options
+	);
+	exit 0;
+}
+
+my $tree = newTree();
+my @datasetNames;
+my $set = 0;
+my $useMag;
+
+foreach my $input ( @ARGV )
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	my %magnitudes;
+	my $totalMagnitude;
+	
+	if ( defined $magFile )
+	{
+		print "   Loading magnitudes from $magFile...\n";
+		loadMagnitudes($magFile, \%magnitudes);
+		$useMag = 1;
+	}
+	
+	print "   Reading classifications from $fileName...\n";
+	
+	open INFILE, "<$fileName" or die $!;
+	
+	<INFILE>; # eat header
+	
+	while ( my $line = <INFILE> )
+	{
+		chomp $line;
+		
+		my ($readID, $classification) = split /\t/, $line;
+		my @lineage = split /;/, $classification;
+		my $magnitude = 1;
+		
+		if ( %magnitudes )
+		{
+			if ( defined $magnitudes{$readID} )
+			{
+				$magnitude = $magnitudes{$readID};
+			}
+			else
+			{
+				ktWarn("Query ID \"$readID\" doesn't exist in magnitude file; using 1.");
+			}
+		}
+		
+		addByLineage($tree, $set, \@lineage, $readID, $magnitude);
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+	
+	close INFILE;
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'magnitudeUnassigned',
+	'count',
+	'unassigned'
+);
+
+my @attributeDisplayNames =
+(
+	$useMag ? 'Magnitude' : undef,
+	$useMag ? 'Unassigned magnitude' : undef,
+	'Count',
+	'Unassigned'
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+);
+
diff --git a/KronaTools/scripts/ImportGalaxy.pl b/KronaTools/scripts/ImportGalaxy.pl
new file mode 100755
index 0000000..61bb976
--- /dev/null
+++ b/KronaTools/scripts/ImportGalaxy.pl
@@ -0,0 +1,149 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+my @options =
+qw(
+	out
+	name
+	combine
+	depth
+	url
+	postUrl
+);
+
+# set defaults
+#
+setOption('out', 'galaxy.krona.html');
+setOption('name', 'root');
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+		'Creates a Krona chart based Galaxy taxonomic representations.',
+		'tax_rep',
+		'Results from the "Fetch taxonomic representation" or "Find lowest
+diagnostic rank" tools in Galaxy.',
+		0,
+		1,
+		\@options
+	);
+	exit 0;
+}
+
+my @ranks =
+qw(
+	superkingdom
+	kingdom
+	subkingdom
+	superphylum
+	phylum
+	subphylum
+	superclass
+	class
+	subclass
+	superorder
+	order
+	suborder
+	superfamily
+	family
+	subfamily
+	tribe
+	subtribe
+	genus
+	subgenus
+	species
+	subspecies
+);
+
+my $tree = newTree();
+my @datasetNames;
+my $set = 0;
+
+foreach my $input ( @ARGV )
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $fileName...\n";
+	
+	open INFILE, "<$fileName" or die $!;
+	
+	while ( my $line = <INFILE> )
+	{
+		chomp $line;
+		
+		my @lineage = split /\t/, $line;
+		
+		# eat GI
+		#
+		if ( @lineage > 24 )
+		{
+			@lineage = @lineage[0..23];
+		}
+		
+		my $queryID = shift @lineage;
+		my $taxID = shift @lineage;
+		shift @lineage; # eat root
+		
+		map { if ( $_ eq 'n' ) { $_ = '' } } @lineage;
+		
+		addByLineage($tree, $set, \@lineage, $queryID, undef, undef, \@ranks);
+#		print "$taxID : @lineage\n";
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+	
+	close INFILE;
+}
+
+my @attributeNames =
+(
+	'count',
+	'unassigned',
+	'rank',
+);
+
+my @attributeDisplayNames =
+(
+	'Reads',
+	'Unassigned',
+	'Rank',
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames
+);
+
diff --git a/KronaTools/scripts/ImportKrona.pl b/KronaTools/scripts/ImportKrona.pl
new file mode 100755
index 0000000..b7c8caf
--- /dev/null
+++ b/KronaTools/scripts/ImportKrona.pl
@@ -0,0 +1,138 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+# defaults
+#
+setOption('out', 'krona.krona.html');
+setOption('hueBad', undef);
+setOption('hueGood', undef);
+setOption('name', undef);
+
+my @options =
+qw(
+	out
+	name
+	combine
+	depth
+	hueBad
+	hueGood
+	url
+	postUrl
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+"Creates a Krona chart from the data in other Krona charts.",
+		"krona_chart",
+		"Krona HTML file created with KronaTools or the Krona Excel Template",
+		1,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+
+my $dataset = 0;
+my $nodeID = 0;
+
+my @attributeNames;
+my @attributeDisplayNames;
+my %attributeDisplayByNames;
+
+my @datasetNames;
+
+my $line;
+
+foreach my $input (@ARGV)
+{
+	print "Reading $input...\n";
+	
+	open XML, $input or die "Could not open $input";
+	
+	while ( $line !~ /<krona/ )
+	{
+		$line = <XML>;
+	}
+	
+	while ( $line = <XML> )
+	{
+		if ( $line =~ /<attribute display="([^"]+)".*>([^<]+)<\/attribute>/ )
+		{
+			if ( $dataset == 0 )
+			{
+				push @attributeNames, $2;
+				push @attributeDisplayNames, $1;
+				$attributeDisplayByNames{$2} = $1;
+			}
+			elsif ( ! $attributeDisplayByNames{$2} || $attributeDisplayByNames{$2} ne $1 )
+			{
+				ktDie("$input is not compatible with the first chart (\"$ARGV[0]\")");
+			}
+		}
+		elsif ( $line =~ /<dataset>([^<]+)<\/dataset>/ )
+		{
+			push @datasetNames, $1;
+		}
+		elsif ( $line =~ /<color attribute="score" hueStart="(\d+)" hueEnd="(\d+)"/ )
+		{
+			if ( ! defined getOption('hueBad') )
+			{
+				setOption('hueBad', $1);
+			}
+			
+			if ( ! defined getOption('hueGood') )
+			{
+				setOption('hueGood', $2);
+			}
+		}
+		elsif ( $line =~ /<node name="([^"]*)"/ )
+		{
+			if ( $dataset == 0 && ! defined getOption('name') )
+			{
+				setOption('name', $1);
+			}
+			
+			addXML($tree, \*XML, $dataset, $input);
+		}
+	}
+	
+	close XML;
+	
+	$dataset = @datasetNames;
+}
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('hueBad'),
+	getOption('hueGood')
+);
diff --git a/KronaTools/scripts/ImportMETAREP-EC.pl b/KronaTools/scripts/ImportMETAREP-EC.pl
new file mode 100755
index 0000000..2639f58
--- /dev/null
+++ b/KronaTools/scripts/ImportMETAREP-EC.pl
@@ -0,0 +1,141 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('out', 'metarep-ec.krona.html');
+setOption('name', 'root');
+
+my @options =
+qw(
+	out
+	name
+	combine
+	include
+	depth
+	url
+	postUrl
+	verbose
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+'Creates a Krona chart of abundances of EC (Enzyme Commission) numbers in METAREP
+data folders. By default, queries with no EC number will be ignored (see -i).',
+		$KronaTools::argumentNames{'metarep'},
+		$KronaTools::argumentDescriptions{'metarep'},
+		0,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+
+print "Loading EC names...\n";
+loadEC();
+
+my $set = 0;
+my @datasetNames;
+
+foreach my $input (@ARGV)
+{
+	my ($folder, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $folder...\n";
+	
+	if ( -e "$folder/annotation.tab" )
+	{
+		open IN, "<$folder/annotation.tab" or die $!;
+	}
+	else
+	{
+		open IN, "gunzip -c $folder/annotation.tab.gz |" or die
+			"Couldn't open gzipped annotation file in $folder.";
+	}
+	
+	while ( my $line = <IN> )
+	{
+		my @values = split /\t/, $line;
+		
+		my $readID = $values[0];
+		my $ec = $values[11];
+		
+		while ( $ec =~ s/\.-$// ) {}; # repeatedly remove trailing '.-'
+		
+		if ( $ec ne '' && $ec !~ /^[\d\.]+$/ )
+		{
+			ktWarn("$readID: Bad EC ('$values[11]'); ignoring.");
+			$ec = '';
+		}
+		if ( $ec || getOption('include') )
+		{
+			my @ecs;
+			
+			if ( $ec )
+			{
+				@ecs = split /\./, $ec;
+			}
+			
+			addByEC($tree, $set, \@ecs, $readID);
+		}
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+	
+	close IN;
+}
+
+my @attributeNames =
+(
+	'count',
+	'unassigned',
+	'ec',
+);
+
+my @attributeDisplayNames =
+(
+	'Peptides',
+	'Unassigned',
+	'EC'
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames
+);
+
diff --git a/KronaTools/scripts/ImportMETAREP-blast.pl b/KronaTools/scripts/ImportMETAREP-blast.pl
new file mode 100755
index 0000000..899342d
--- /dev/null
+++ b/KronaTools/scripts/ImportMETAREP-blast.pl
@@ -0,0 +1,218 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('out', 'metarep-blast.krona.html');
+setOption('name', 'root');
+
+my @options =
+qw(
+	out
+	name
+	random
+	percentIdentity
+	bitScore
+	combine
+	depth
+	noRank
+	hueBad
+	hueGood
+	url
+	postUrl
+	taxonomy
+	verbose
+	
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+
+	printUsage
+	(
+'Creates a Krona chart by classifying reads based on BLAST results in METAREP
+data folders.',
+		$KronaTools::argumentNames{'metarep'},
+		$KronaTools::argumentDescriptions{'metarep'},
+		0,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+
+print "Loading taxonomy...\n";
+loadTaxonomy();
+
+my $lastReadID;
+my $set = 0;
+my @datasetNames;
+my $zeroEVal;
+
+foreach my $input (@ARGV)
+{
+	my ($folder, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $folder...\n";
+	
+	if ( -e "$folder/blast.tab" )
+	{
+		open IN, "<$folder/blast.tab" or
+			ktDie("Couldn't open blast file in $folder");
+	}
+	else
+	{
+		open IN, "gunzip -c $folder/blast.tab.gz |" or
+			ktDie("Couldn't open gzipped blast file in $folder.");
+	}
+	
+	while ( my $line = <IN> )
+	{
+		chomp $line;
+		my @values = split /\t/, $line;
+		
+		my $readID = $values[0];
+		
+		if ( $readID ne $lastReadID )
+		{
+			my $ties = 0;
+			my %lcaSet;
+			my @randomArray;
+			my $taxID;
+			my $readLength = $values[2];
+			
+			while ( $values[15] =~ /taxon:(\d+)/g )
+			{
+				my $newTaxID = $1;
+				
+				if ( ! taxIDExists($newTaxID) )
+				{
+					ktWarn("$readID: Taxon $newTaxID does not exist; using root.\n");
+					$newTaxID = 1;
+				}
+				
+				if ( getOption('random') )
+				{
+					push @randomArray, $newTaxID;
+				}
+				else
+				{
+					$lcaSet{$newTaxID} = 1;
+				}
+			}
+			
+			if ( getOption('random') )
+			{
+				$taxID = $randomArray[int(rand(scalar @randomArray))];
+			}
+			else
+			{
+				$taxID = taxLowestCommonAncestor(keys %lcaSet);
+			}
+			
+			if ( getOption('verbose') )
+			{
+				print "$readID\ttaxID: $taxID\n";
+			}
+			
+			my $score;
+			
+			if ( getOption('percentIdentity') )
+			{
+				$score = $values[11];
+			}
+			elsif ( getOption('bitScore') )
+			{
+				$score = $values[12];
+			}
+			else
+			{
+				if ( $values[19] > 0 )
+				{
+					$score = log $values[19];
+				}
+				else
+				{
+					$score = $KronaTools::minEVal;
+					$zeroEVal = 1;
+				}
+			}
+			
+			addByTaxID($tree, $set, $taxID, $readID, undef, $score);
+		}
+		
+		$lastReadID = $readID;
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+	
+	close IN;
+}
+
+if ( $zeroEVal )
+{
+	ktWarn("Couldn't take base-10 log for e-values of 0.  Approximated as $KronaTools::minEval.");
+}
+
+my @attributeNames =
+(
+	'count',
+	'unassigned',
+	'taxon',
+	'rank',
+	'score',
+);
+
+my @attributeDisplayNames =
+(
+	'Peptides',
+	'Unassigned',
+	'Tax ID',
+	'Rank',
+	getScoreName()
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('bitScore') || getOption('percentIdentity') ?
+		getOption('hueBad') : 
+		getOption('hueGood'),
+	getOption('bitScore') || getOption('percentIdentity') ?
+		getOption('hueGood') :
+		getOption('hueBad')
+);
+
diff --git a/KronaTools/scripts/ImportMGRAST.pl b/KronaTools/scripts/ImportMGRAST.pl
new file mode 100755
index 0000000..889847f
--- /dev/null
+++ b/KronaTools/scripts/ImportMGRAST.pl
@@ -0,0 +1,157 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('name', 'all');
+setOption('out', 'mg-rast.krona.html');
+
+my @options =
+qw(
+	out
+	name
+	combine
+	depth
+	hueBad
+	hueGood
+	percentIdentity
+	url
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+		'Creates a Krona chart from MG-RAST organism or functional analyses.',
+		'mgrast_table',
+		'A table exported from MG-RAST. It can be from organism or functional
+analysis, but all tables being imported should be consistent.',
+		0,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+my @ranks;
+my @datasetNames;
+my $set = 0;
+
+foreach my $input ( @ARGV )
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $fileName...\n";
+	
+	open INFILE, "<$fileName" or die $!;
+	
+	my $header = <INFILE>;
+	my $offset;
+	my @fields = split /\t/, $header;
+	
+	# remove metagenome and source (if present)
+	#
+	shift @fields;
+	#
+	if ( $fields[0] eq 'source' )
+	{
+		shift @fields;
+		$offset = 2;
+	}
+	else
+	{
+		$offset = 1;
+	}
+	
+	my $i = 0;
+	
+	while ( $fields[0] ne 'abundance' )
+	{
+		$ranks[$i] = shift @fields;
+		$i++;
+	}
+	
+	while ( my $line = <INFILE> )
+	{
+		chomp $line;
+		
+		my @data = split /\t/, $line;
+		my $magnitude = $data[$offset + @ranks];
+		my $score;
+		
+		my @lineage = @data[$offset..($offset + @ranks - 1)];
+		
+		map { if ( $_ eq '-' ) { $_ = '' } } @lineage;
+		
+		if ( getOption('percentIdentity') )
+		{
+			$score = $data[$offset + 2 + @ranks];
+		}
+		else
+		{
+			$score = $data[$offset + 1 + @ranks];
+		}
+		
+		addByLineage($tree, $set, \@lineage, undef, $magnitude, $score, \@ranks);
+	}
+	
+	close INFILE;
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'magnitudeUnassigned',
+	'score',
+	'rank'
+);
+
+my @attributeDisplayNames =
+(
+	'Abundance',
+	'Unassigned',
+	getScoreName(),
+	'Rank'
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('percentIdentity') ? getOption('hueBad') : getOption('hueGood'),
+	getOption('percentIdentity') ? getOption('hueGood') : getOption('hueBad')
+);
+
diff --git a/KronaTools/scripts/ImportPHMMER.pl b/KronaTools/scripts/ImportPHMMER.pl
new file mode 100755
index 0000000..03ffc68
--- /dev/null
+++ b/KronaTools/scripts/ImportPHMMER.pl
@@ -0,0 +1,261 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+my $totalMag;
+my $outFile = 'report.krona.html';
+
+setOption('out', 'phmmer.krona.html');
+setOption('name', 'Root');
+
+my @options =
+qw(
+	out
+	factor
+	random
+	bitScore
+	combine
+	depth
+	hueBad
+	hueGood
+	local
+	standalone
+	url
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+ 	printUsage
+ 	(
+ 		'Infers taxonomic abundance from PHMMER results.',
+		'phmmer_output',
+		'PHMMER output.',
+		1,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+
+# load taxonomy
+
+print "Loading taxonomy...\n";
+loadTaxonomy();
+
+# parse PHMMER results
+
+my $set = 0;
+my @datasetNames;
+my $useMag;
+my $zeroEVal;
+
+foreach my $input (@ARGV)
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	my %magnitudes;
+	
+	# load magnitudes
+	
+	if ( defined $magFile )
+	{
+		print "   Loading magnitudes from $magFile...\n";
+		loadMagnitudes($magFile, \%magnitudes);
+		$useMag = 1;
+	}
+	
+	print "Importing $fileName...\n";
+	
+	open PHMMER, "<$fileName" or ktDie("Couldn't open $fileName");
+	
+	my $lastQueryID;
+	my $topScore;
+	my $topEVal;
+	my $ties;
+	my $taxID;
+	my $totalScore;
+	
+	while ( 1 )
+	{
+		my $line = <PHMMER>;
+		
+		chomp $line;
+		
+		if ( $line =~ /^#/ )
+		{
+			next;
+		}
+		
+		my
+		(
+			$hitID,
+			$blank1,
+			$queryID,
+			$blank2,
+			$eVal,
+			$bitScore
+		) = split /\s+/, $line;
+		
+		if ( $queryID ne $lastQueryID )
+		{
+			if (  defined $taxID )
+			{
+				# add the chosen hit from the last queryID
+				
+				addByTaxID
+				(
+					$tree,
+					$set,
+					$taxID,
+					$lastQueryID,
+					$magnitudes{$lastQueryID},
+					$totalScore / $ties
+				);
+			}
+			
+			$ties = 0;
+			$totalScore = 0;
+		}
+		
+		if ( ! defined $hitID )
+		{
+			last; # EOF
+		}
+		
+		$hitID =~ /gi\|(\d+)/;
+		
+		my $gi = $1;
+		
+		if # this is a 'best' hit if...
+		(
+			$queryID ne $lastQueryID || # new query ID (including null at EOF)
+			$eVal <= getOption('factor') * $topEVal # within e-val factor
+		)
+		{
+			# add score for average
+			#
+			if ( getOption('bitScore') )
+			{
+				$totalScore += $bitScore;
+			}
+			else
+			{
+				if ( $eVal > 0 )
+				{
+					$totalScore += (log $eVal) / log 10;
+				}
+				else
+				{
+					$totalScore += $KronaTools::minEVal;
+					$zeroEVal = 1;
+				}
+			}
+			#
+			$ties++;
+			
+			if # use this hit if...
+			(
+				! getOption('random') || # using LCA
+				$queryID ne $lastQueryID || # new query ID
+				int(rand($ties)) == 0 # randomly chosen to replace other hit
+			)
+			{
+				my $newTaxID = getTaxIDFromGI($gi);
+				
+				if ( ! $newTaxID )
+				{
+					$newTaxID = 1;
+				}
+				
+				if ( $queryID ne $lastQueryID || getOption('random') )
+				{
+					$taxID = $newTaxID;
+				}
+				else
+				{
+					$taxID = taxLowestCommonAncestor($taxID, $newTaxID);
+				}
+			}
+		}
+		
+		if ( $queryID ne $lastQueryID )
+		{
+			$topScore = $bitScore;
+			$topEVal = $eVal;
+		}
+		
+		$lastQueryID = $queryID;
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+}
+
+if ( $zeroEVal )
+{
+		ktWarn("Input contained e-values of 0. Approximated log[10] of 0 as $KronaTools::minEVal.");
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'count',
+	'unassigned',
+	'taxon',
+	'rank',
+	'score'
+);
+
+my @attributeDisplayNames =
+(
+	$useMag ? 'Magnitude' : undef,
+	'Count',
+	'Unassigned',
+	'Tax ID',
+	'Rank',
+	getScoreName(),
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('bitScore') ?
+		getOption('hueBad') : 
+		getOption('hueGood'),
+	getOption('bitScore') ?
+		getOption('hueGood') :
+		getOption('hueBad')
+);
diff --git a/KronaTools/scripts/ImportPhymmBL.pl b/KronaTools/scripts/ImportPhymmBL.pl
new file mode 100755
index 0000000..764de9d
--- /dev/null
+++ b/KronaTools/scripts/ImportPhymmBL.pl
@@ -0,0 +1,223 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('name', 'all');
+setOption('key', 0);
+
+my @options =
+qw(
+	out
+	name
+	minConfidence
+	combine
+	depth
+	hueBad
+	hueGood
+	phymm
+	url
+	postUrl
+);
+
+getKronaOptions(@options);
+
+if ( @ARGV < 1 )
+{
+	setOption('out', 'phymm(bl).krona.html');
+	
+	printUsage
+	(
+		'Creates a Krona chart of Phymm or PhymmBL results.
+
+Note: Since confidence scores are not given for species/subspecies
+classifications, they inheret confidence scores from genus classifications.',
+		'phymmbl_results',
+		'PhymmBL results files (results.03.*). Results can also be from Phymm
+alone (results.01.*), but ' . getOptionString('phymm') . ' must be specified.',
+		1,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+if ( ! defined getOption('out') )
+{
+	if ( getOption('phymm') )
+	{
+		setOption('out', 'phymm.krona.html');
+	}
+	else
+	{
+		setOption('out', 'phymmbl.krona.html');
+	}
+}
+
+my @ranks =
+(
+	'Phylum',
+	'Class',
+	'Order',
+	'Family',
+	'Genus',
+	'Species/Subspecies'
+);
+
+my $tree = newTree();
+my $set = 0;
+my @datasetNames;
+my $useMag;
+
+foreach my $input ( @ARGV )
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	my %magnitudes;
+	
+	print "Importing $fileName...\n";
+	
+	if ( defined $magFile )
+	{
+		print "   Loading magnitudes from $magFile...\n";
+		loadMagnitudes($magFile, \%magnitudes);
+		$useMag = 1;
+	}
+	
+	print "   Reading classifications from $fileName...\n";
+	
+	open INFILE, "<$fileName" or die $!;
+	
+	<INFILE>; # eat header
+	
+	while ( my $line = <INFILE> )
+	{
+		chomp $line;
+		
+		my @values = split /\t/, $line;
+		my @lineage;
+		my $scores;
+		
+		my $readID = shift @values;
+		
+		if ( getOption('phymm') )
+		{
+			my ($species, $score);
+			
+			($species, $score, @lineage) = @values;
+			
+			$scores = $score;
+			
+			@lineage = reverse @lineage;
+			
+			push @lineage, $species;
+		}
+		else
+		{
+			if ( @values < 12 )
+			{
+				my $phymm = getOptionString('phymm');
+				ktDie("Not enough fields in $fileName.  Is it a PhymmBL result file (see $phymm)?");
+			}
+			
+			$scores = ();
+			
+			$values[1] = $values[3]; # use genus conf for species
+			
+			for ( my $i = 0; $i < @values; $i += 2 )
+			{
+				unshift @lineage, $values[$i];
+				unshift @$scores, $values[$i + 1];
+			}
+		}
+		
+		for ( my $i = 0; $i < @lineage; $i++ )
+		{
+			$lineage[$i] = decode($lineage[$i]);
+		}
+		
+		map { if ( $_ eq '' ) { $_ = 'unknown' } } @lineage;
+		
+		addByLineage($tree, $set, \@lineage, $readID, $magnitudes{$readID}, $scores, \@ranks);
+	}
+	
+	close INFILE;
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+}
+
+# tree output
+
+my @attributeNames =
+(
+	'magnitude',
+	'count',
+	'unassigned',
+	'rank',
+	'score'
+);
+
+my @attributeDisplayNames =
+(
+	$useMag ? 'Magnitude' : undef,
+	'Count',
+	'Unassigned',
+	'Rank',
+	getOption('phymm') ? 'Avg. score' : 'Avg. confidence'
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('hueBad'),
+	getOption('hueGood')
+);
+
+
+# subroutines
+
+sub decode
+{
+	# return special characters in place of their Phymm placeholders
+	
+	my ($string) = @_;
+	
+	$string =~ s/_/ /g;
+	$string =~ s/UNDERSCORE/_/g;
+	$string =~ s/SLASH/\//g;
+	$string =~ s/LPAREN/\(/g;
+	$string =~ s/RPAREN/\)/g;
+	$string =~ s/SINGLEQUOTE/'/g;
+	$string =~ s/DOUBLEQUOTE/"/g;
+	$string =~ s/COLONCOLON/:/g;
+	$string =~ s/SEMICOLON/;/g;
+	
+	return $string;
+}
+
diff --git a/KronaTools/scripts/ImportRDP.pl b/KronaTools/scripts/ImportRDP.pl
new file mode 100755
index 0000000..30cc6bf
--- /dev/null
+++ b/KronaTools/scripts/ImportRDP.pl
@@ -0,0 +1,207 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('name', 'root');
+setOption('out', 'rdp.krona.html');
+
+my @options =
+qw(
+	out
+	name
+	combine
+	minConfidence
+	depth
+	hueBad
+	hueGood
+	url
+	postUrl
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+		'Creates a Krona chart from RDP classifications.',
+		'rdp_details',
+		'RDP assignment details downloaded as text from the RDP Classifier web
+portal or output by the command line RDP Classifier or Multiclassifier.',
+		0,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my @webRanks =
+(
+	'Domain',
+	'Phylum',
+	'Class',
+	'Order',
+	'Family',
+	'Genus'
+);
+
+my $tree = newTree();
+
+my @datasetNames;
+my $set = 0;
+
+foreach my $input ( @ARGV )
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $fileName...\n";
+	
+	open INFILE, "<$fileName" or die $!;
+	
+	my $webFormat;
+	my $line = <INFILE>;
+	
+	if ( $line =~ /^\s*$/ || $line =~ /^Classifier:/ || $line =~ /;( +|[+-]?);/ )
+	{
+		$webFormat = 1;
+		
+		print "   Web portal format detected.\n";
+		
+		while ( $line !~ /;( +|[+-]?);/ )
+		{
+			$line = <INFILE>;
+			
+			if ( ! $line )
+			{
+				ktDie("Classifications not found in \"$fileName\". Is it an \"Assignment detail\" file?");
+			}
+		}
+	}
+	else
+	{
+		print "   Command line format detected.\n";
+	}
+	
+	while ( $line )
+	{
+		my $queryID;
+		my @lineage;
+		my @ranks;
+		my @scores;
+		my $allRanks;
+		
+		chomp $line;
+		
+		if ( $line eq '' ) {next}
+		
+		if ( $webFormat )
+		{
+			chop $line; # last '%'
+			
+			my @fields = split /["%]?; ?"?/, $line;
+			
+			$queryID = $fields[0];
+			
+			for ( my $i = 2; $i < @fields; $i += 2 )
+			{
+				if ( $fields[$i] eq 'Root' )
+				{
+					$allRanks = 1;
+					next;
+				}
+				
+				push @lineage, $fields[$i];
+				push @scores, $fields[$i + 1];
+			}
+		}
+		else
+		{
+			my @fields = split /"?\t"?/, $line;
+			
+			$queryID = $fields[0];
+			
+			for ( my $i = 2; $i < @fields; $i += 3 )
+			{
+				if ( $fields[$i] eq 'Root' )
+				{
+					next;
+				}
+				
+				push @lineage, $fields[$i];
+				push @ranks, $fields[$i + 1];
+				push @scores, $fields[$i + 2] * 100;
+			}
+		}
+		
+		addByLineage
+		(
+			$tree,
+			$set,
+			\@lineage,
+			$queryID,
+			undef,
+			\@scores,
+			$webFormat ? ($allRanks ? undef : \@webRanks) : \@ranks
+		);
+		
+		$line = <INFILE>;
+	}
+	
+	close INFILE;
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+}
+
+my @attributeNames =
+(
+	'count',
+	'unassigned',
+	'score',
+	'rank'
+);
+
+my @attributeDisplayNames =
+(
+	'Count',
+	'Unassigned',
+	'Avg. % Confidence',
+	'Rank'
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('hueBad'),
+	getOption('hueGood')
+);
+
diff --git a/KronaTools/scripts/ImportRDPComparison.pl b/KronaTools/scripts/ImportRDPComparison.pl
new file mode 100755
index 0000000..8348644
--- /dev/null
+++ b/KronaTools/scripts/ImportRDPComparison.pl
@@ -0,0 +1,182 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('name', 'root');
+setOption('out', 'rdp.comp.krona.html');
+
+# Prevent the magnitude and score of each classification from being added to its
+# ancestors. This is necessary because internal nodes are explicitly listed in
+# the RDP comparison results.
+#
+setOption('leafAdd', 1);
+
+my @options =
+qw(
+	out
+	name
+	depth
+	hueBad
+	hueGood
+	url
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	my $scriptName = getScriptName();
+	
+	printHeader("KronaTools $KronaTools::version - $scriptName");
+	print
+'Creates a Krona chart from an RDP library comparison.
+';
+	printHeader('Usage');
+	print
+"$scriptName [options] rdp_comparison [name1] [name2]
+
+";
+	printColumns
+	(
+		'   rdp_comparison',
+		'RDP comparison result downloaded as text.',
+		'   name',
+'A name for each library to appear in the chart. The default is "Library
+[1/2]".',
+	);
+	
+	printOptions(@options);
+	
+	exit 0;
+}
+
+my @ranks =
+(
+	'Domain',
+	'Phylum',
+	'Class',
+	'Order',
+	'Family',
+	'Genus',
+);
+
+my $tree = newTree();
+my ($fileName, $name1, $name2) = @ARGV;
+
+if ( ! defined $name1 )
+{
+	$name1 = 'Library 1';
+	$name2 = 'Library 2';
+}
+
+my @datasetNames = ($name1, $name2);
+
+my @lineage;
+my @scores;
+my $minScores;
+
+print "Importing $fileName...\n";
+
+open INFILE, "<$fileName" or die $!;
+
+my $line;
+
+do
+{
+	$line = <INFILE>;
+	
+	if ( ! $line )
+	{
+		ktDie("\"$fileName\" is not RDP comparison file.");
+	}
+}
+while ( <INFILE> !~ /^Rank/ );
+
+while ( my $line = <INFILE> )
+{
+	chomp $line;
+	
+	my ($rank, $lineageString, $taxon, $mag1, $mag2, $score) = split / \| /, $line;
+	
+	if ( $taxon )
+	{
+		my @lineage = split /"?;"?/, $lineageString;
+		
+		if ( substr($taxon, 0, 1) eq '"' && substr($taxon, -1, 1) eq '"' )
+		{
+			$taxon = substr($taxon, 1);
+			chop $taxon;
+		}
+		
+		$taxon =~ s/"/"/g;
+		
+		my @scores;
+		
+		if ( $rank ) # no rank means unclassified, so no score
+		{
+			push @lineage, $taxon;
+			shift @lineage; # remove root
+			
+			if ( $score )
+			{
+				$score = log $score;
+			}
+			else
+			{
+				$score = $KronaTools::minEVal;
+				$minScores++;
+			}
+			
+			addByLineage($tree, 0, \@lineage, undef, $mag1, $score);
+			addByLineage($tree, 1, \@lineage, undef, $mag2, $score);
+		}
+	}
+}
+
+close INFILE;
+
+if ( $minScores)
+{
+	print "\nWarning: Couldn't log[10] of 0 for $minScores scores.  Approximated as $KronaTools::minEVal.\n\n";
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'score'
+);
+
+my @attributeDisplayNames =
+(
+	'Abundance',
+	'Log significance'
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	getOption('hueGood'),
+	getOption('hueBad')
+);
+
diff --git a/KronaTools/scripts/ImportTaxonomy.pl b/KronaTools/scripts/ImportTaxonomy.pl
new file mode 100755
index 0000000..20719d1
--- /dev/null
+++ b/KronaTools/scripts/ImportTaxonomy.pl
@@ -0,0 +1,263 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('out', 'taxonomy.krona.html');
+setOption('name', 'Root');
+
+my @options =
+qw(
+	out
+	name
+	include
+	combine
+	queryCol
+	taxCol
+	scoreCol
+	magCol
+	depth
+	noRank
+	hueBad
+	hueGood
+	url
+	postUrl
+	taxonomy
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+		'Creates a Krona chart based on taxonomy IDs and, optionally, magnitudes
+and scores. Taxonomy IDs corresponding to a rank of "no rank" in the database
+will be assigned to their parents to make the hierarchy less cluttered (e.g.
+"Cellular organisms" will be assigned to "root").',
+		'taxonomy',
+		'Tab-delimited file with taxonomy IDs and (optionally) query IDs,
+magnitudes and scores. By default, query IDs, taxonomy IDs and scores will be
+taken from columns 1, 2 and 3, respectively (see -q, -t, -s, and -m). Lines
+beginning with "#" will be ignored.',
+		1,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+if ( optionsConflict('queryCol', 'taxCol', 'magCol', 'scoreCol') )
+{
+	ktWarn('Query column already in use; not reading query IDs.');
+	setOption('queryCol', undef);
+}
+
+if ( optionsConflict('scoreCol', 'taxCol', 'magCol') )
+{
+	ktWarn('Score column already in use; not reading scores.');
+	setOption('scoreCol', undef);
+}
+
+if ( optionsConflict('magCol', 'taxCol') )
+{
+	ktWarn('Magnitude column already in use; not reading magnitudes.');
+	setOption('magCol', undef);
+}
+
+my $tree = newTree();
+
+print "Loading taxonomy...\n";
+loadTaxonomy();
+
+my $set = 0;
+my @datasetNames;
+my $useScore = 1; # is score column present?
+my $eVal; # is score e-value (inferred by negative scores)?
+my $useMag = getOption('magCol'); # using magnitude values?
+
+foreach my $input (@ARGV)
+{
+	my ($file, $magFile, $name) = parseDataset($input);
+	
+	my %magnitudes;
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	print "Importing $file...\n";
+	
+	# load magnitudes
+	
+	if ( defined $magFile )
+	{
+		if ( getOption('queryCol') )
+		{
+			print "   Loading magnitudes from $magFile...\n";
+			loadMagnitudes($magFile, \%magnitudes);
+			$useMag = 1;
+		}
+		else
+		{
+			ktWarn("Query column not defined; not reading magnitudes from \"$magFile\".");
+		}
+	}
+	
+	open IN, "<$file" or ktDie("Couldn't open \"$file\".");
+	
+	while ( <IN> )
+	{
+		if ( /^#/ )
+		{
+			next;
+		}
+		
+		chomp;
+		
+		my @fields = split /\t/;
+		
+		my $queryID;
+		my $taxID = $fields[getOption('taxCol') - 1];
+		my $magnitude;
+		my $score;
+		
+		if ( getOption('queryCol') )
+		{
+			$queryID = $fields[getOption('queryCol') - 1];
+		}
+		
+		if ( getOption('scoreCol') )
+		{
+			$score = $fields[getOption('scoreCol') - 1];
+		}
+		
+		if ( defined $queryID && defined $magnitudes{$queryID} )
+		{
+			$magnitude = $magnitudes{$queryID};
+		}
+		elsif ( defined getOption('magCol') )
+		{
+			$magnitude = $fields[getOption('magCol') - 1];
+		}
+		
+		if ( $taxID == -2 )
+		{
+			$taxID = 1;
+		}
+		elsif ( $taxID == -1 )
+		{
+			if ( getOption('include') )
+			{
+				$taxID = 0;
+			}
+			else
+			{
+				next;
+			}
+		}
+		
+		if ( ! defined $score )
+		{
+			# all lines must have score to be used
+			
+			$useScore = 0;
+		}
+		
+		if ( $score < 0 )
+		{
+			# score is probably e-value; flip colors
+			
+			$eVal = 1;
+		}
+		
+		addByTaxID($tree, $set, $taxID, $queryID, $magnitude, $score);
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+	
+	close IN;
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'magnitudeUnassigned',
+	'count',
+	'unassigned',
+	'taxon',
+	'rank',
+);
+
+my @attributeDisplayNames =
+(
+	$useMag ? 'Magnitude' : (getOption('queryCol') ? undef : 'Count'),
+	$useMag ? 'Unassigned magnitude' : (getOption('queryCol') ? undef : 'Unassigned'),
+	getOption('queryCol') ? 'Count' : undef,
+	getOption('queryCol') ? 'Unassigned' : undef,
+	'Taxon',
+	'Rank',
+);
+
+my @scoreArgs;
+
+if ( $useScore )
+{
+	push @attributeNames, 'score';
+	push @attributeDisplayNames, 'Avg. score';
+	
+	@scoreArgs =
+	(
+		$eVal ? getOption('hueGood') : getOption('hueBad'),
+		$eVal ? getOption('hueBad') : getOption('hueGood')
+	)
+}
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames,
+	@scoreArgs
+);
+
+sub optionsConflict
+{
+	my ($option, @others) = @_;
+	
+	if ( getOption($option) )
+	{
+		foreach my $other ( @others )
+		{
+			if ( getOption($option) == getOption($other) )
+			{
+				return 1;
+			}
+		}
+	}
+	
+	return 0;
+}
diff --git a/KronaTools/scripts/ImportText.pl b/KronaTools/scripts/ImportText.pl
new file mode 100755
index 0000000..aafb051
--- /dev/null
+++ b/KronaTools/scripts/ImportText.pl
@@ -0,0 +1,123 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('out', 'text.krona.html');
+setOption('name', 'all');
+
+my @options =
+qw(
+	out
+	name
+	noMag
+	combine
+	url
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	printUsage
+	(
+		'Creates a Krona chart from text files listing quantities and
+lineages.',
+		'text',
+		'Tab-delimited text file. Each line should be a number followed by a
+list of wedges to contribute to (starting from the highest level). If no wedges
+are listed (and just a quantity is given), it will contribute to the top level.
+If the same lineage is listed more than once, the values will be added.
+Quantities can be omitted if -q is specified. Lines beginning with "#" will be
+ignored.',
+		0,
+		1,
+		\@options
+	);
+	
+	exit 0;
+}
+
+my $tree = newTree();
+my @datasetNames;
+my $set = 0;
+
+foreach my $input ( @ARGV )
+{
+	my ($fileName, $magFile, $name) = parseDataset($input);
+	
+	if ( ! getOption('combine') )
+	{
+		push @datasetNames, $name;
+	}
+	
+	open INFILE, "<$fileName" or die $!;
+	
+	while ( <INFILE> )
+	{
+		if ( /^#/ )
+		{
+			next;
+		}
+		
+		chomp;
+		
+		my @lineage = split /\t/;
+		my $magnitude;
+		
+		if ( getOption('noMag') )
+		{
+			$magnitude = 1;
+		}
+		else
+		{
+			$magnitude = shift @lineage;
+		}
+		
+		addByLineage($tree, $set, \@lineage, undef, $magnitude);
+	}
+	
+	if ( ! getOption('combine') )
+	{
+		$set++;
+	}
+	
+	close INFILE;
+}
+
+my @attributeNames =
+(
+	'magnitude',
+	'magnitudeUnassigned'
+);
+
+my @attributeDisplayNames =
+(
+	'Total',
+	'Unassigned'
+);
+
+writeTree
+(
+	$tree,
+	\@attributeNames,
+	\@attributeDisplayNames,
+	\@datasetNames
+);
diff --git a/KronaTools/scripts/ImportXML.pl b/KronaTools/scripts/ImportXML.pl
new file mode 100755
index 0000000..f15417b
--- /dev/null
+++ b/KronaTools/scripts/ImportXML.pl
@@ -0,0 +1,77 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+BEGIN
+{
+	use File::Basename;
+	use Cwd 'abs_path';
+	use lib dirname(abs_path($0)) . "/../lib";
+	use KronaTools;
+}
+
+setOption('out', 'xml.krona.html');
+
+my @options =
+qw(
+	out
+	url
+);
+
+getKronaOptions(@options);
+
+if
+(
+	@ARGV < 1
+)
+{
+	my $scriptName = getScriptName();
+	
+	printHeader("KronaTools $KronaTools::version - $scriptName");
+	print
+'Creates a Krona chart from xml data describing each node and how the chart
+should look.
+';
+	printHeader('Usage');
+	print
+"$scriptName [options] <XML_file>
+
+";
+	printColumns
+	(
+		'   XML_file',
+'A file containing XML tags that specify chart attributes and describe the node
+hierarchy. An XML header is not necessary. For a complete description of XML
+tags, see: https://sourceforge.net/p/krona/wiki/KronaTools/'
+	);
+	printOptions(@options);
+	exit;
+}
+
+my ($xmlFile) = @ARGV;
+
+my $outFile = getOption('out');
+
+print "Writing $outFile...\n";
+
+open OUT, ">$outFile";
+print OUT htmlHeader();
+
+open IN, "<$xmlFile" or die $!;
+
+while ( <IN> )
+{
+	print OUT $_;
+}
+
+close IN;
+
+print OUT htmlFooter();
+close OUT;
diff --git a/KronaTools/scripts/accession2taxid.make b/KronaTools/scripts/accession2taxid.make
new file mode 100644
index 0000000..9d0f352
--- /dev/null
+++ b/KronaTools/scripts/accession2taxid.make
@@ -0,0 +1,32 @@
+ACC2TAXID=\
+	dead_nucl.accession2taxid \
+	dead_prot.accession2taxid \
+	dead_wgs.accession2taxid \
+	nucl_est.accession2taxid \
+	nucl_gb.accession2taxid \
+	nucl_gss.accession2taxid \
+	nucl_wgs.accession2taxid \
+	prot.accession2taxid
+
+ACC2TAXID_SORTED=$(ACC2TAXID:.accession2taxid=.accession2taxid.sorted)
+
+../all.accession2taxid.sorted : $(ACC2TAXID_SORTED)
+	@echo "Merging sorted..."
+	@LC_ALL=C sort -m $(ACC2TAXID_SORTED) > $@
+	@rm $(ACC2TAXID_SORTED)
+
+SORT := grep -v accession | sed 's/\.[[:digit:]]*//' | LC_ALL=C sort
+
+%.accession2taxid.sorted : %.accession2taxid
+	@echo "Sorting $<..."
+	@cut -f 2,3 $< | ${SORT} > $@
+ifneq ("${PRESERVE}", "1")
+	@rm $<
+endif
+
+%.accession2taxid.sorted : %.accession2taxid.gz
+	@echo "Sorting $<..."
+	@gunzip -c $< | cut -f 2,3 | ${SORT} > $@
+ifneq ("${PRESERVE}", "1")
+	@rm $<
+endif
diff --git a/KronaTools/scripts/diffCombine.pl b/KronaTools/scripts/diffCombine.pl
new file mode 100755
index 0000000..f85310e
--- /dev/null
+++ b/KronaTools/scripts/diffCombine.pl
@@ -0,0 +1,37 @@
+#!/usr/bin/env perl
+
+use strict;
+
+my @totals;
+
+foreach my $file ( @ARGV )
+{
+	open IN, "<$file" or die $!;
+	
+	# eat headers
+	#
+	<IN>;
+	<IN>;
+	
+	my $i = 0;
+	
+	while ( my $line = <IN> )
+	{
+		my @vals = split /,/, $line;
+		
+		for ( my $j = 0; $j < 3; $j++ )
+		{
+			$totals[$i][$j] += $vals[$j + 2];
+		}
+		
+		$i++;
+	}
+	
+	close IN;
+}
+
+print ",,,Human\n";
+print ",,top hit,hit,no hit\n";
+print ",top hit,", join(',', @{$totals[0]}), "\n";
+print "NHP,hit,", join(',', @{$totals[1]}), "\n";
+print ",no hit,", join(',', @{$totals[2]}), "\n";
diff --git a/KronaTools/scripts/differentiate.pl b/KronaTools/scripts/differentiate.pl
new file mode 100755
index 0000000..74b7ed1
--- /dev/null
+++ b/KronaTools/scripts/differentiate.pl
@@ -0,0 +1,127 @@
+#!/usr/bin/env perl
+
+use strict;
+
+# get the path of this script; dependencies should be in the same directory
+#
+my $scriptPath;
+BEGIN
+{
+	use Cwd 'abs_path';
+	abs_path($0) =~ /(.*)\//;
+	$scriptPath = $1;
+}
+use lib "$scriptPath/../lib";
+
+use Krona;
+
+if ( @ARGV < 3 )
+{
+	print "differentiate.pl <target_taxID> <bg_taxID> <blast...>\n";
+	exit;
+}
+
+my ($target, $bg, @files) = @ARGV;
+
+my @totals;
+
+loadTaxonomy();
+
+foreach my $file ( @files )
+{
+	open BLAST, "<$file";
+	
+	my $lastQueryID;
+	my $topScore;
+	
+	# 0 = top hit, 1 = hit, 2 = no hit
+	#
+	my $targetHit;
+	my $bgHit;
+	
+	while ( 1 )
+	{
+		my $line = <BLAST>;
+		
+		chomp $line;
+		
+		if ( $line =~ /^#/ )
+		{
+			next;
+		}
+		
+		my
+		(
+			$queryID,
+			$hitID,
+			$identity,
+			$length,
+			$mismatches,
+			$gaps,
+			$queryStart,
+			$queryEnd,
+			$subjectStart,
+			$subjectEnd,
+			$eVal,
+			$bitScore
+		) = split /\t/, $line;
+		
+		if ( $queryID ne $lastQueryID && defined $lastQueryID )
+		{
+			$totals[$bgHit][$targetHit]++;
+			#print "$targetHit\t$bgHit\n\n";
+		}
+		
+		if ( ! defined $hitID )
+		{
+			last; # EOF
+		}
+		
+		$hitID =~ /gi\|(\d+)/;
+		
+		my $gi = $1;
+		
+		my $taxID = getTaxID($gi);
+		my $name = getName($taxID);
+		
+		#print "$queryID\t$taxID\t$bitScore\t$name\n";
+		
+		if ( $queryID ne $lastQueryID )
+		{
+			$topScore = $bitScore;
+			$targetHit = 2;
+			$bgHit = 2;
+		}
+		
+		if ( contains($target, $taxID) )
+		{
+			if ( $bitScore == $topScore )
+			{
+				$targetHit = 0;
+			}
+			elsif ( $targetHit == 2 )
+			{
+				$targetHit = 1;
+			}
+		}
+		elsif ( contains($bg, $taxID) )
+		{
+			if ( $bitScore == $topScore )
+			{
+				$bgHit = 0;
+			}
+			elsif ( $bgHit == 2 )
+			{
+				$bgHit = 1;
+			}
+		}
+		
+		$lastQueryID = $queryID;
+	}
+}
+
+print ",,,Human\n";
+print ",,top hit,hit,no hit\n";
+print ",top hit,", join(',', @{$totals[0]}), "\n";
+print "NHP,hit,", join(',', @{$totals[1]}), "\n";
+print ",no hit,", join(',', @{$totals[2]}), "\n";
diff --git a/KronaTools/scripts/extractNodeData.pl b/KronaTools/scripts/extractNodeData.pl
new file mode 100755
index 0000000..6380b3f
--- /dev/null
+++ b/KronaTools/scripts/extractNodeData.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+
+while (my $line = <>)
+{
+	if ( $line =~ /<node/ )
+	{
+		my $name;
+		my $magnitude;
+		my $score;
+		
+		$line =~ /name=\"([^"]+)\"/;
+		$name = $1;
+		$line =~ /magnitude=\"([^"]+)\"/;
+		$magnitude = $1;
+		$line =~ /score=\"([^"]+)\"/;
+		$score = $1;
+		
+		print "$name\t$magnitude\t$score\n";
+	}
+}
diff --git a/KronaTools/scripts/extractTaxonomy.pl b/KronaTools/scripts/extractTaxonomy.pl
new file mode 100755
index 0000000..e3f66a0
--- /dev/null
+++ b/KronaTools/scripts/extractTaxonomy.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/env perl
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+
+use strict;
+
+
+my ($taxonomy) = @ARGV;
+
+my %data;
+
+# load scientific names for each tax ID
+
+open NAMES, "<$taxonomy/names.dmp" or die "Couldn't open names.dmp";
+
+while ( my $line = <NAMES> )
+{
+	my ($id, $name, $uniqueName, $class) = split /\t\|\t/, $line;
+	
+	if ( $class =~ /scientific name/ )
+	{
+		if ( ! defined $data{$id} )
+		{
+			$data{$id} = ();
+		}
+		
+		$data{$id}->{'name'} = $name;
+	}
+}
+
+close NAMES;
+
+# load parents and ranks for each tax ID
+
+open NODES, "<$taxonomy/nodes.dmp" or die "Couldn't open nodes.dmp";
+
+while ( my $line = <NODES> )
+{
+	$line =~ /(\d+)\t\|\t(\d+)\t\|\t([^\t]+)/;
+	
+	my $id = $1;
+	
+	if ( ! defined $data{$id} )
+	{
+		$data{$id} = ();
+	}
+	
+	$data{$id}->{'parent'} = $2;
+	$data{$id}->{'rank'} = $3;
+}
+
+close NODES;
+
+open OUT, ">$taxonomy/taxonomy.tab" or die "Couldn't write to taxonomy.tab";
+
+foreach my $id ( sort {$a <=> $b} keys %data )
+{
+	print OUT join "\t",
+	(
+		$id,
+		depth($id),
+		getParent($id),
+		$data{$id}->{'rank'},
+		$data{$id}->{'name'}
+	);
+	print OUT "\n";
+}
+
+close OUT;
+
+
+sub depth
+{
+	my ($id) = @_;
+	
+	if ( $id == 1 )
+	{
+		return 0;
+	}
+	else
+	{
+		return depth(getParent($id)) + 1;
+	}
+}
+
+sub getParent
+{
+	my ($id) = @_;
+	return $data{$id}->{'parent'};
+}
diff --git a/KronaTools/scripts/formatEC.pl b/KronaTools/scripts/formatEC.pl
new file mode 100755
index 0000000..24c05a5
--- /dev/null
+++ b/KronaTools/scripts/formatEC.pl
@@ -0,0 +1,59 @@
+#!/usr/bin/env perl
+
+use strict;
+
+my ($fileClass, $fileEnzyme) = @ARGV;
+
+open CLASS, $fileClass or die $fileClass;
+
+while ( <CLASS> )
+{
+	chomp;
+	
+	if ( /^(\d+)\.\s*(\d+|-)\.\s*(\d+|-)\.\s*(\d+|-)\s+(.+)\.$/ )
+	{
+		my @classes = ($1, $2, $3, $4);
+		my $desc = $5;
+		
+		while ( $classes[-1] eq '-' )
+		{
+			pop @classes;
+		}
+		
+		print join '.', @classes;
+		print "\t$desc\n";
+	}
+}
+
+close CLASS;
+
+my $id;
+my $desc;
+
+open ENZYME, $fileEnzyme or die $fileEnzyme;
+
+while ( <ENZYME> )
+{
+	chomp;
+	
+	if ( /^ID\s+(\d+\.\d+\.\d+\.\d+)$/ )
+	{
+		$id = $1;
+	}
+	elsif ( /^DE\s+(.+)\.$/ )
+	{
+		$desc = $1;
+	}
+	elsif ( /^\/\/$/ )
+	{
+		if ( defined $id && defined $desc )
+		{
+			print "$id\t$desc\n";
+		}
+		
+		undef $id;
+		undef $desc;
+	}
+}
+
+close ENZYME;
diff --git a/KronaTools/scripts/getContigMagnitudesCA.pl b/KronaTools/scripts/getContigMagnitudesCA.pl
new file mode 100755
index 0000000..8a93353
--- /dev/null
+++ b/KronaTools/scripts/getContigMagnitudesCA.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/env perl
+
+# Copyright 2011 Brian Ondov
+# 
+# This file is part of Radiant.
+# 
+# Radiant is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# Radiant is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with Radiant.  If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+
+
+if ( @ARGV < 2 )
+{
+	print '
+
+getContigMagnitudesCA.pl <assembly_folder> <output>
+
+Writes a magnitude file for use with import scripts.  The magnitude of each
+contig will be the total number of bases assigned to it (also equal to
+depth * length).
+
+';
+	exit;
+}
+
+my ($wgsFolder, $output) = @ARGV;
+
+
+my ($frgctgFile) = glob "$wgsFolder/9-terminator/*.posmap.frgctg";
+my %contigMagnitudes;
+
+open POSMAP, "<$frgctgFile" or die $!;
+
+while ( my $line = <POSMAP> )
+{
+	my ($read, $contigID, $start, $end, $strand) = split /\t/, $line;
+	
+	my $contigName = 'ctg' . $contigID;
+	
+	$contigMagnitudes{$contigName} += $end - $start + 1;
+}
+
+close POSMAP;
+
+open OUT, ">$output" or die $!;
+
+foreach my $contig ( keys %contigMagnitudes )
+{
+	print OUT "$contig\t$contigMagnitudes{$contig}\n";
+}
+
+close OUT;
diff --git a/KronaTools/scripts/indexGIs.pl b/KronaTools/scripts/indexGIs.pl
new file mode 100755
index 0000000..efeccf9
--- /dev/null
+++ b/KronaTools/scripts/indexGIs.pl
@@ -0,0 +1,81 @@
+#!/usr/bin/env perl
+
+# converts the large text files into uniform records so they can be randomly
+# accessed instead of slow serial searches
+
+my ($taxonomy) = @ARGV;
+
+use strict;
+
+indexGI();
+
+sub indexGI
+{
+	# GIs are unique across nucleotide and protein records, so we want to
+	# combine the taxid lists into one file in which each taxid is a 4 byte
+	# field and missing GIs have blank fields to preserve position.
+	
+	my ($file) = @_;
+	
+	open NUC, "<$taxonomy/gi_taxid_nucl.dmp" or die $!;
+	open PRO, "<$taxonomy/gi_taxid_prot.dmp" or die $!;
+	
+	open OUT, ">$taxonomy/gi_taxid.dat" or die $!;
+	
+	my $lastGI = -1;
+	my $giNuc;
+	my $giPro;
+	my $taxIDNuc;
+	my $taxIDPro;
+	
+	# initalize records
+	#
+	($giNuc, $taxIDNuc) = getRecord(\*NUC);
+	($giPro, $taxIDPro) = getRecord(\*PRO);
+	
+	while ( defined $giNuc || defined $giPro )
+	{
+		my $gi;
+		my $taxID;
+		
+		# Use the record with the smallest gi and advance to the next record
+		# from its file.
+		#
+		if ( ! defined $giPro || defined $giNuc && $giNuc < $giPro )
+		{
+			$gi = $giNuc;
+			$taxID = $taxIDNuc;
+			
+			($giNuc, $taxIDNuc) = getRecord(\*NUC);
+		}
+		else
+		{
+			$gi = $giPro;
+			$taxID = $taxIDPro;
+			
+			($giPro, $taxIDPro) = getRecord(\*PRO);
+		}
+		
+		# fill in GIs that weren't listed with 0s
+		#
+		for ( my $i = $lastGI + 1; $i < $gi; $i++ )
+		{
+			print OUT pack "L", 0;
+		}
+		
+		print OUT pack "L", int($taxID);
+		
+		$lastGI = $gi;
+	}
+	
+	close OUT;
+	
+	close PRO;
+	close NUC;
+}
+
+sub getRecord
+{
+	my $fh = shift;
+	return split /\t/, <$fh>;
+}
diff --git a/KronaTools/scripts/taxonomy.make b/KronaTools/scripts/taxonomy.make
new file mode 100644
index 0000000..f82560a
--- /dev/null
+++ b/KronaTools/scripts/taxonomy.make
@@ -0,0 +1,23 @@
+TAX=\
+	citations.dmp \
+	delnodes.dmp \
+	division.dmp \
+	gc.prt \
+	gencode.dmp \
+	merged.dmp \
+	names.dmp \
+	nodes.dmp \
+	readme.txt
+
+taxonomy.tab : names.dmp
+	@echo "Extracting taxonomy..."
+	@$(KTPATH)/scripts/extractTaxonomy.pl .
+
+names.dmp : $(wildcard taxdump.tar taxdump.tar.gz)
+	@tar -xmf $<
+
+.PHONY clean :
+clean :
+	@rm -f taxdump.tar
+	@rm -f taxdump.tar.gz
+	@rm -f $(TAX)
diff --git a/KronaTools/src/krona-1.1.js b/KronaTools/src/krona-1.1.js
new file mode 100644
index 0000000..d7e65cf
--- /dev/null
+++ b/KronaTools/src/krona-1.1.js
@@ -0,0 +1,5983 @@
+{//-----------------------------------------------------------------------------
+// 
+// PURPOSE
+// 
+// Krona is a flexible tool for exploring the relative proportions of
+// hierarchical data, such as metagenomic classifications, using a
+// radial, space-filling display. It is implemented using HTML5 and
+// JavaScript, allowing charts to be explored locally or served over the
+// Internet, requiring only a current version of any major web
+// browser. Krona charts can be created using an Excel template or from
+// common bioinformatic formats using the provided conversion scripts.
+// 
+// 
+// COPYRIGHT LICENSE
+// 
+// Copyright (c) 2011, Battelle National Biodefense Institute (BNBI);
+// all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+// Adam Phillippy
+// 
+// This Software was prepared for the Department of Homeland Security
+// (DHS) by the Battelle National Biodefense Institute, LLC (BNBI) as
+// part of contract HSHQDC-07-C-00020 to manage and operate the National
+// Biodefense Analysis and Countermeasures Center (NBACC), a Federally
+// Funded Research and Development Center.
+// 
+// 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 Battelle National Biodefense Institute 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
+// HOLDER 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.
+// 
+// 
+// TRADEMARK LICENSE
+// 
+// KRONA(TM) is a trademark of the Department of Homeland Security, and use
+// of the trademark is subject to the following conditions:
+// 
+// * Distribution of the unchanged, official code/software using the
+//   KRONA(TM) mark is hereby permitted by the Department of Homeland
+//   Security, provided that the software is distributed without charge
+//   and modification.
+// 
+// * Distribution of altered source code/software using the KRONA(TM) mark
+//   is not permitted unless written permission has been granted by the
+//   Department of Homeland Security.
+// 
+// 
+// FOR MORE INFORMATION VISIT
+// 
+// http://krona.sourceforge.net
+// 
+//-----------------------------------------------------------------------------
+}
+
+var canvas;
+var context;
+var svg; // for snapshot mode
+var collapse = true;
+var collapseCheckBox;
+var collapseLast;
+var compress;
+var compressCheckBox;
+var maxAbsoluteDepthText;
+var maxAbsoluteDepthButtonDecrease;
+var maxAbsoluteDepthButtonIncrease;
+var fontSize = 11;
+var fontSizeText;
+var fontSizeButtonDecrease;
+var fontSizeButtonIncrease;
+var fontSizeLast;
+var shorten;
+var shortenCheckBox;
+var maxAbsoluteDepth;
+var backButton;
+var upButton;
+var forwardButton;
+var snapshotButton;
+var snapshotMode = false;
+var details;
+var detailsName;
+var search;
+var searchResults;
+var nSearchResults;
+var useHueCheckBox;
+var useHueDiv;
+var datasetDropDown;
+var datasetButtonLast;
+var datasetButtonPrev;
+var datasetButtonNext;
+var keyControl;
+var showKeys = true;
+var linkButton;
+var linkText;
+
+// Node references. Note that the meanings of 'selected' and 'focused' are
+// swapped in the docs.
+//
+var head; // the root of the entire tree
+var selectedNode = 0; // the root of the current view
+var focusNode = 0; // a node chosen for more info (single-click)
+var highlightedNode = 0; // mouse hover node
+var highlightingHidden = false;
+var nodes = new Array();
+var currentNodeID = 0; // to iterate while loading
+
+var nodeHistory = new Array();
+var nodeHistoryPosition = 0;
+
+// store non-Krona GET variables so they can be passed on to links
+//
+var getVariables = new Array();
+
+// selectedNodeLast is separate from the history, since we need to check
+// properties of the last node viewed when browsing through the history
+//
+var selectedNodeLast = 0;
+var zoomOut = false;
+
+// temporary zoom-in while holding the mouse button on a wedge
+//
+var quickLook = false; // true when in quick look state
+var mouseDown = false;
+var mouseDownTime; // to detect mouse button hold
+var quickLookHoldLength = 200;
+
+var imageWidth;
+var imageHeight;
+var centerX;
+var centerY;
+var gRadius;
+var updateViewNeeded = false;
+
+// Determines the angle that the pie chart starts at.  90 degrees makes the
+// center label consistent with the children.
+//
+var rotationOffset = Math.PI / 2;
+
+var buffer = 100;
+
+// The maps are the small pie charts showing the current slice being viewed.
+//
+var mapBuffer = 10;
+var mapRadius = 0;
+var maxMapRadius = 25;
+var mapWidth = 150;
+var maxLabelOverhang = Math.PI * 4.18;
+
+// Keys are the labeled boxes for slices in the highest level that are too thin
+// to label.
+//
+var maxKeySizeFactor = 2; // will be multiplied by font size
+var keySize;
+var keys;
+var keyBuffer = 10;
+var currentKey;
+var keyMinTextLeft;
+var keyMinAngle;
+
+var minRingWidthFactor = 5; // will be multiplied by font size
+var maxPossibleDepth; // the theoretical max that can be displayed
+var maxDisplayDepth; // the actual depth that will be displayed
+var headerHeight = 0;//document.getElementById('options').clientHeight;
+var historySpacingFactor = 1.6; // will be multiplied by font size
+var historyAlphaDelta = .25;
+
+// appearance
+//
+var lineOpacity = 0.3;
+var saturation = 0.5;
+var lightnessBase = 0.6;
+var lightnessMax = .8;
+var thinLineWidth = .3;
+var highlightLineWidth = 1.5;
+var labelBoxBuffer = 6;
+var labelBoxRounding = 15;
+var labelWidthFudge = 1.05; // The width of unshortened labels are set slightly
+							// longer than the name width so the animation
+							// finishes faster.
+var fontNormal;
+var fontBold;
+var fontFamily = 'sans-serif';
+//var fontFaceBold = 'bold Arial';
+var nodeRadius;
+var angleFactor;
+var tickLength;
+var compressedRadii;
+
+// colors
+//
+var highlightFill = 'rgba(255, 255, 255, .3)';
+var colorUnclassified = 'rgb(220,220,220)';
+
+// label staggering
+//
+var labelOffsets; // will store the current offset at each depth
+//
+// This will store pointers to the last node that had a label in each offset (or "track") of a
+// each depth.  These will be used to shorten neighboring labels that would overlap.
+// The [nLabelNodes] index will store the last node with a radial label.
+// labelFirstNodes is the same, but to check for going all the way around and
+// overlapping the first labels.
+//
+var labelLastNodes;
+var labelFirstNodes;
+//
+var nLabelOffsets = 3; // the number of offsets to use
+
+var mouseX = -1;
+var mouseY = -1;
+
+// tweening
+//
+var progress = 0; // for tweening; goes from 0 to 1.
+var progressLast = 0;
+var tweenFactor = 0; // progress converted by a curve for a smoother effect.
+var tweenLength = 850; // in ms
+var tweenCurvature = 13;
+//
+// tweenMax is used to scale the sigmoid function so its range is [0,1] for the
+// domain [0,1]
+//
+var tweenMax = 1 / (1 + Math.exp(-tweenCurvature / 2));
+//
+var tweenStartTime;
+
+// for framerate debug
+//
+var tweenFrames = 0;
+var fpsDisplay = document.getElementById('frameRate');
+
+// Arrays to translate xml attribute names into displayable attribute names
+//
+var attributeNames = new Array();
+var attributeDisplayNames = new Array();
+//
+var magnitudeIndex; // the index of attribute arrays used for magnitude
+var membersAssignedIndex;
+var membersSummaryIndex;
+
+// For defining gradients
+//
+var hueDisplayName;
+var hueStopPositions;
+var hueStopHues;
+var hueStopText;
+
+// multiple datasets
+//
+var currentDataset = 0;
+var lastDataset = 0;
+var datasets = 1;
+var datasetNames;
+var datasetSelectSize = 40;
+var datasetAlpha = new Tween(0, 0);
+var datasetWidths = new Array();
+var datasetChanged;
+var datasetSelectWidth = 120;
+
+document.body.style.overflow = "hidden";
+window.onload = load;
+
+var image;
+var hiddenPattern;
+
+canvas = document.getElementById('canvas');
+context = canvas.getContext('2d');
+
+function resize()
+{
+	imageWidth = window.innerWidth;
+	imageHeight = window.innerHeight;
+	
+	if ( ! snapshotMode )
+	{
+		context.canvas.width = imageWidth;
+		context.canvas.height = imageHeight;
+	}
+	
+	var minDimension = imageWidth - mapWidth > imageHeight ?
+		imageHeight :
+		imageWidth - mapWidth;
+	
+	maxMapRadius = minDimension * .03;
+	buffer = minDimension * .1;
+	margin = minDimension * .015;
+	var leftMargin = datasets > 1 ? datasetSelectWidth + 30 : 0;
+	centerX = (imageWidth - mapWidth - leftMargin) / 2 + leftMargin;
+	centerY = imageHeight / 2;
+	gRadius = minDimension / 2 - buffer;
+	//context.font = '11px sans-serif';
+}
+
+function handleResize()
+{
+	updateViewNeeded = true;
+}
+
+function Tween(start, end)
+{
+	this.start = start;
+	this.end = end;
+	this.current = this.start;
+	
+	this.current = function()
+	{
+		if ( progress == 1 || this.start == this.end )
+		{
+			return this.end;
+		}
+		else
+		{
+			return this.start + tweenFactor * (this.end - this.start);
+		}
+	};
+	
+	this.setTarget = function(target)
+	{
+		this.start = this.current();
+		this.end = target;
+	}
+}
+
+function Node()
+{
+	this.id = currentNodeID;
+	currentNodeID++;
+	nodes[this.id] = this;
+	
+	this.angleStart = new Tween(Math.PI, 0);
+	this.angleEnd = new Tween(Math.PI, 0);
+	this.radiusInner = new Tween(1, 1);
+	this.labelRadius = new Tween(1, 1);
+	this.labelWidth = new Tween(0, 0);
+	this.scale = new Tween(1, 1); // TEMP
+	this.radiusOuter = new Tween(1, 1);
+	
+	this.r = new Tween(255, 255);
+	this.g = new Tween(255, 255);
+	this.b = new Tween(255, 255);
+	
+	this.alphaLabel = new Tween(0, 1);
+	this.alphaLine = new Tween(0, 1);
+	this.alphaArc = new Tween(0, 0);
+	this.alphaWedge = new Tween(0, 1);
+	this.alphaOther = new Tween(0, 1);
+	this.alphaPattern = new Tween(0, 0);
+	this.children = Array();
+	this.parent = 0;
+	
+	this.attributes = new Array();
+	
+	this.addChild = function(child)
+	{
+		this.children.push(child);
+	};
+	
+	this.addLabelNode = function(depth, labelOffset)
+	{
+		if ( labelHeadNodes[depth][labelOffset] == 0 )
+		{
+			// this will become the head node for this list
+			
+			labelHeadNodes[depth][labelOffset] = this;
+			this.labelPrev = this;
+		}
+		
+		var head = labelHeadNodes[depth][labelOffset];
+		
+		this.labelNext = head;
+		this.labelPrev = head.labelPrev;
+		head.labelPrev.labelNext = this;
+		head.labelPrev = this;
+	}
+	
+	this.canDisplayDepth = function()
+	{
+		// whether this node is at a depth that can be displayed, according
+		// to the max absolute depth
+		
+		return this.depth <= maxAbsoluteDepth;
+	}
+	
+	this.canDisplayHistory = function()
+	{
+		var radiusInner;
+		
+		if ( compress )
+		{
+			radiusInner = compressedRadii[0];
+		}
+		else
+		{
+			radiusInner = nodeRadius;
+		}
+		
+		return (
+			-this.labelRadius.end * gRadius +
+			historySpacingFactor * fontSize / 2 <
+			radiusInner * gRadius
+			);
+	}
+	
+	this.canDisplayLabelCurrent = function()
+	{
+		return (
+			(this.angleEnd.current() - this.angleStart.current()) *
+			(this.radiusInner.current() * gRadius + gRadius) >=
+			minWidth());
+	}
+	
+	this.checkHighlight = function()
+	{
+		if ( this.children.length == 0 && this == focusNode )
+		{
+			//return false;
+		}
+		
+		if ( this.hide )
+		{
+			return false;
+		}
+		
+		if ( this.radiusInner.end == 1 )
+		{
+			// compressed to the outside; don't check
+			
+			return false;
+		}
+		
+		var highlighted = false;
+		
+		var angleStartCurrent = this.angleStart.current() + rotationOffset;
+		var angleEndCurrent = this.angleEnd.current() + rotationOffset;
+		var radiusInner = this.radiusInner.current() * gRadius;
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			highlighted = this.children[i].checkHighlight();
+			
+			if ( highlighted )
+			{
+				return true;
+			}
+		}
+		
+		if ( this != selectedNode && ! this.getCollapse() )
+		{
+			context.beginPath();
+			context.arc(0, 0, radiusInner, angleStartCurrent, angleEndCurrent, false);
+			context.arc(0, 0, gRadius, angleEndCurrent, angleStartCurrent, true);
+			context.closePath();
+			
+			if ( context.isPointInPath(mouseX - centerX, mouseY - centerY) )
+			{
+				highlighted = true;
+			}
+			
+			if
+			(
+				! highlighted &&
+				(angleEndCurrent - angleStartCurrent) *
+				(radiusInner + gRadius) <
+				minWidth() &&
+				this.getDepth() == selectedNode.getDepth() + 1
+			)
+			{
+				if ( showKeys && this.checkHighlightKey() )
+				{
+					highlighted = true;
+				}
+			}
+		}
+		
+		if ( highlighted )
+		{
+			if ( this != highlightedNode )
+			{
+			//	document.body.style.cursor='pointer';
+			}
+			
+			highlightedNode = this;
+		}
+		
+		return highlighted;
+	}
+	
+	this.checkHighlightCenter = function()
+	{
+		if ( ! this.canDisplayHistory() )
+		{
+			return;
+		}
+		
+		var cx = centerX;
+		var cy = centerY - this.labelRadius.end * gRadius;
+		//var dim = context.measureText(this.name);
+		
+		var width = this.nameWidth;
+		
+		if ( this.searchResultChildren() )
+		{
+			var results = searchResultString(this.searchResultChildren());
+			var dim = context.measureText(results);
+			width += dim.width;
+		}
+		
+		if
+		(
+			mouseX > cx - width / 2 &&
+			mouseX < cx + width / 2 &&
+			mouseY > cy - historySpacingFactor * fontSize / 2 &&
+			mouseY < cy + historySpacingFactor * fontSize / 2
+		)
+		{
+			highlightedNode = this;
+			return;
+		}
+		
+		if ( this.getParent() )
+		{
+			this.getParent().checkHighlightCenter();
+		}
+	}
+	
+	this.checkHighlightKey = function()
+	{
+		var offset = keyOffset();
+		
+		var xMin = imageWidth - keySize - margin - this.keyNameWidth - keyBuffer;
+		var xMax = imageWidth - margin;
+		var yMin = offset;
+		var yMax = offset + keySize;
+		
+		currentKey++;
+		
+		return (
+			mouseX > xMin &&
+			mouseX < xMax &&
+			mouseY > yMin &&
+			mouseY < yMax);
+	}
+	
+	this.checkHighlightMap = function()
+	{
+		if ( this.parent )
+		{
+			this.parent.checkHighlightMap();
+		}
+		
+		if ( this.getCollapse() || this == focusNode )
+		{
+			return;
+		}
+		
+		var box = this.getMapPosition();
+		
+		if
+		(
+			mouseX > box.x - mapRadius &&
+			mouseX < box.x + mapRadius &&
+			mouseY > box.y - mapRadius &&
+			mouseY < box.y + mapRadius
+		)
+		{
+			highlightedNode = this;
+		}
+	}
+	
+/*	this.collapse = function()
+	{
+		for (var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i] = this.children[i].collapse();
+		}
+		
+		if
+		(
+			this.children.length == 1 &&
+			this.children[0].magnitude == this.magnitude
+		)
+		{
+			this.children[0].parent = this.parent;
+			this.children[0].getDepth() = this.parent.getDepth() + 1;
+			return this.children[0];
+		}
+		else
+		{
+			return this;
+		}
+	}
+*/	
+	this.draw = function(labelMode, selected, searchHighlighted)
+	{
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+//		var hidden = false;
+		
+		if ( selectedNode == this )
+		{
+			selected = true;
+		}
+		
+		var angleStartCurrent = this.angleStart.current() + rotationOffset;
+		var angleEndCurrent = this.angleEnd.current() + rotationOffset;
+		var radiusInner = this.radiusInner.current() * gRadius;
+		var canDisplayLabelCurrent = this.canDisplayLabelCurrent();
+		var hiddenSearchResults = false;
+		
+/*		if ( ! this.hide )
+		{
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				if ( this.children[i].hide && this.children[i].searchResults )
+				{
+					hiddenSearchResults = true;
+				}
+			}
+		}
+*/		
+		var drawChildren =
+			( ! this.hide || ! this.hidePrev && progress < 1 ) &&
+			( ! this.hideAlone || ! this.hideAlonePrev && progress < 1 );
+		
+//		if ( this.alphaWedge.current() > 0 || this.alphaLabel.current() > 0 )
+		{
+			var lastChildAngleEnd;
+			
+			if ( this.hasChildren() )//canDisplayChildren )
+			{
+				lastChildAngleEnd =
+					this.children[this.children.length - 1].angleEnd.current()
+					+ rotationOffset;
+			}
+			
+			if ( labelMode )
+			{
+				var drawRadial =
+				!(
+					this.parent &&
+					this.parent != selectedNode &&
+					angleEndCurrent == this.parent.angleEnd.current() + rotationOffset
+				);
+				
+				if ( angleStartCurrent != angleEndCurrent )
+				{
+					this.drawLines(angleStartCurrent, angleEndCurrent, radiusInner, drawRadial, selected);
+				}
+				
+				var alphaOtherCurrent = this.alphaOther.current();
+				var childRadiusInner;
+				
+				if ( this == selectedNode || alphaOtherCurrent )
+				{
+					childRadiusInner =
+						this.children[this.children.length - 1].radiusInner.current() * gRadius;
+				}
+				
+				if ( this == selectedNode )
+				{
+					this.drawReferenceRings(childRadiusInner);
+				}
+				
+				if
+				(
+					selected &&
+					! searchHighlighted &&
+					this != selectedNode &&
+					(
+						this.isSearchResult ||
+						this.hideAlone && this.searchResultChildren() ||
+						false
+//						this.hide &&
+//						this.containsSearchResult
+					)
+				)
+				{
+					context.globalAlpha = this.alphaWedge.current();
+					
+					drawWedge
+					(
+						angleStartCurrent,
+						angleEndCurrent,
+						radiusInner,
+						gRadius,
+						highlightFill,
+						0,
+						true
+					);
+					
+					if
+					(
+						this.keyed &&
+						! showKeys &&
+						this.searchResults &&
+						! searchHighlighted &&
+						this != highlightedNode &&
+						this != focusNode
+					)
+					{
+						var angle = (angleEndCurrent + angleStartCurrent) / 2;
+						this.drawLabel(angle, true, false, true, true);
+					}
+					
+					//this.drawHighlight(false);
+					searchHighlighted = true;
+				}
+				
+				if
+				(
+					this == selectedNode ||
+//					true
+					//(canDisplayLabelCurrent) &&
+					this != highlightedNode &&
+					this != focusNode
+				)
+				{
+					if ( this.radial != this.radialPrev && this.alphaLabel.end == 1 )
+					{
+						context.globalAlpha = tweenFactor;
+					}
+					else
+					{
+						context.globalAlpha = this.alphaLabel.current();
+					}
+					
+					this.drawLabel
+					(
+						(angleStartCurrent + angleEndCurrent) / 2,
+						this.hideAlone && this.searchResultChildren() ||
+						(this.isSearchResult || hiddenSearchResults) && selected,
+						this == selectedNode && ! this.radial,
+						selected,
+						this.radial
+					);
+					
+					if ( this.radial != this.radialPrev && this.alphaLabel.start == 1 && progress < 1 )
+					{
+						context.globalAlpha = 1 - tweenFactor;
+						
+						this.drawLabel
+						(
+							(angleStartCurrent + angleEndCurrent) / 2,
+							(this.isSearchResult || hiddenSearchResults) && selected,
+							this == selectedNodeLast && ! this.radialPrev,
+							selected,
+							this.radialPrev
+						);
+					}
+				}
+				
+				if
+				(
+					alphaOtherCurrent &&
+					lastChildAngleEnd != null
+				)
+				{
+					if
+					(
+						(angleEndCurrent - lastChildAngleEnd) *
+						(childRadiusInner + gRadius) >=
+						minWidth()
+					)
+					{
+						//context.font = fontNormal;
+						context.globalAlpha = this.alphaOther.current();
+						
+						drawTextPolar
+						(
+							this.getUnclassifiedText(),
+							this.getUnclassifiedPercentage(),
+							(lastChildAngleEnd + angleEndCurrent) / 2,
+							(childRadiusInner + gRadius) / 2,
+							true,
+							false,
+							false,
+							0,
+							0
+						);
+					}
+				}
+				
+				if ( this == selectedNode && this.keyUnclassified && showKeys )
+				{
+					this.drawKey
+					(
+						(lastChildAngleEnd + angleEndCurrent) / 2,
+						false,
+						false
+					);
+				}
+			}
+			else
+			{
+				var alphaWedgeCurrent = this.alphaWedge.current();
+				
+				if ( alphaWedgeCurrent || this.alphaOther.current() )
+				{
+					var currentR = this.r.current();
+					var currentG = this.g.current();
+					var currentB = this.b.current();
+						
+					var fill = rgbText(currentR, currentG, currentB);
+					
+					var radiusOuter;
+					var lastChildAngle;
+					var truncateWedge =
+					(
+						this.hasChildren() &&
+						! this.keyed &&
+						(compress || depth < maxDisplayDepth) &&
+						drawChildren
+					);
+					
+					if ( truncateWedge )
+					{
+						radiusOuter = this.children[0].radiusInner.current() * gRadius;
+					}
+					else
+					{
+						radiusOuter = gRadius;
+					}
+					/*
+					if ( this.hasChildren() )
+					{
+						radiusOuter = this.children[0].getUncollapsed().radiusInner.current() * gRadius + 1;
+					}
+					else
+					{ // TEMP
+						radiusOuter = radiusInner + nodeRadius * gRadius;
+						
+						if ( radiusOuter > gRadius )
+						{
+							radiusOuter = gRadius;
+						}
+					}
+					*/
+					context.globalAlpha = alphaWedgeCurrent;
+					
+					if ( radiusInner != radiusOuter )
+					{
+						drawWedge
+						(
+							angleStartCurrent,
+							angleEndCurrent,
+							radiusInner,
+							radiusOuter,//this.radiusOuter.current() * gRadius,
+							//'rgba(0, 200, 0, .1)',
+							fill,
+							this.alphaPattern.current()
+						);
+						
+						if ( truncateWedge )
+						{
+							// fill in the extra space if the sum of our childrens'
+							// magnitudes is less than ours
+							
+							if ( lastChildAngleEnd < angleEndCurrent )//&& false) // TEMP
+							{
+								if ( radiusOuter > 1 )
+								{
+									// overlap slightly to hide the seam
+									
+	//								radiusOuter -= 1;
+								}
+								
+								if ( alphaWedgeCurrent < 1 )
+								{
+									context.globalAlpha = this.alphaOther.current();
+									drawWedge
+									(
+										lastChildAngleEnd,
+										angleEndCurrent,
+										radiusOuter,
+										gRadius,
+										colorUnclassified,
+										0
+									);
+									context.globalAlpha = alphaWedgeCurrent;
+								}
+								
+								drawWedge
+								(
+									lastChildAngleEnd,
+									angleEndCurrent,
+									radiusOuter,
+									gRadius,//this.radiusOuter.current() * gRadius,
+									//'rgba(200, 0, 0, .1)',
+									fill,
+									this.alphaPattern.current()
+								);
+							}
+						}
+						
+						if ( radiusOuter < gRadius )
+						{
+							// patch up the seam
+							//
+							context.beginPath();
+							context.arc(0, 0, radiusOuter, angleStartCurrent/*lastChildAngleEnd*/, angleEndCurrent, false);
+							context.strokeStyle = fill;
+							context.lineWidth = 1;
+							context.stroke();
+						}
+					}
+					
+					if ( this.keyed && selected && showKeys )//&& progress == 1 )
+					{
+						this.drawKey
+						(
+							(angleStartCurrent + angleEndCurrent) / 2,
+							(
+								this == highlightedNode ||
+								this == focusNode ||
+								this.searchResults
+							),
+							this == highlightedNode || this == focusNode
+						);
+					}
+				}
+			}
+		}
+		
+		if ( drawChildren )
+		{
+			// draw children
+			//
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				if ( this.drawHiddenChildren(i, selected, labelMode, searchHighlighted) )
+				{
+					i = this.children[i].hiddenEnd;
+				}
+				else
+				{
+					this.children[i].draw(labelMode, selected, searchHighlighted);
+				}
+			}
+		}
+	};
+	
+	this.drawHiddenChildren = function
+	(
+		firstHiddenChild,
+		selected,
+		labelMode,
+		searchHighlighted
+	)
+	{
+		var firstChild = this.children[firstHiddenChild];
+		
+		if ( firstChild.hiddenEnd == null || firstChild.radiusInner.current() == 1 )
+		{
+			return false;
+		}
+		
+		for ( var i = firstHiddenChild; i < firstChild.hiddenEnd; i++ )
+		{
+			if ( ! this.children[i].hide || ! this.children[i].hidePrev && progress < 1 )
+			{
+				return false;
+			}
+		}
+		
+		var angleStart = firstChild.angleStart.current() + rotationOffset;
+		var lastChild = this.children[firstChild.hiddenEnd];
+		var angleEnd = lastChild.angleEnd.current() + rotationOffset;
+		var radiusInner = gRadius * firstChild.radiusInner.current();
+		var hiddenChildren = firstChild.hiddenEnd - firstHiddenChild + 1;
+		
+		if ( labelMode )
+		{
+			var hiddenSearchResults = 0;
+			
+			for ( var i = firstHiddenChild; i <= firstChild.hiddenEnd; i++ )
+			{
+				hiddenSearchResults += this.children[i].searchResults;
+			}
+			
+			if
+			(
+				selected &&
+				(angleEnd - angleStart) * 
+				(gRadius + gRadius) >=
+				minWidth() ||
+				hiddenSearchResults
+			)
+			{
+				context.globalAlpha = this.alphaWedge.current();
+				
+				this.drawHiddenLabel
+				(
+					angleStart,
+					angleEnd,
+					hiddenChildren,
+					hiddenSearchResults
+				);
+			}
+		}
+		
+		var drawWedges = true;
+		
+		for ( var i = firstHiddenChild; i <= firstChild.hiddenEnd; i++ )
+		{
+			// all hidden children must be completely hidden to draw together
+			
+			if ( this.children[i].alphaPattern.current() != this.children[i].alphaWedge.current() )
+			{
+				drawWedges = false;
+				break;
+			}
+		}
+		
+		if ( labelMode )
+		{
+			if ( drawWedges )
+			{
+				var drawRadial = (angleEnd < this.angleEnd.current() + rotationOffset);
+				this.drawLines(angleStart, angleEnd, radiusInner, drawRadial);
+			}
+			
+			if ( hiddenSearchResults && ! searchHighlighted )
+			{
+				drawWedge
+				(
+					angleStart,
+					angleEnd,
+					radiusInner,
+					gRadius,//this.radiusOuter.current() * gRadius,
+					highlightFill,
+					0,
+					true
+				);
+			}
+		}
+		else if ( drawWedges )
+		{
+			context.globalAlpha = this.alphaWedge.current();
+			
+			var fill = rgbText
+			(
+				firstChild.r.current(),
+				firstChild.g.current(),
+				firstChild.b.current()
+			);
+			
+			drawWedge
+			(
+				angleStart,
+				angleEnd,
+				radiusInner,
+				gRadius,//this.radiusOuter.current() * gRadius,
+				fill,
+				context.globalAlpha,
+				false
+			);
+		}
+		
+		return drawWedges;
+	}
+	
+	this.drawHiddenLabel = function(angleStart, angleEnd, value, hiddenSearchResults)
+	{
+		var textAngle = (angleStart + angleEnd) / 2;
+		var labelRadius = gRadius + fontSize;//(radiusInner + radius) / 2;
+		
+		drawTick(gRadius - fontSize * .75, fontSize * 1.5, textAngle);
+		drawTextPolar
+		(
+			value.toString() + ' more',
+			0, // inner text
+			textAngle,
+			labelRadius,
+			true, // radial
+			hiddenSearchResults, // bubble
+			this == highlightedNode || this == focusNode, // bold
+			false,
+			hiddenSearchResults
+		);
+	}
+	
+	this.drawHighlight = function(bold)
+	{
+		var angleStartCurrent = this.angleStart.current() + rotationOffset;
+		var angleEndCurrent = this.angleEnd.current() + rotationOffset;
+		var radiusInner = this.radiusInner.current() * gRadius;
+		
+		//this.setHighlightStyle();
+		
+		if ( this == focusNode && this == highlightedNode && this.hasChildren() )
+		{
+//			context.fillStyle = "rgba(255, 255, 255, .3)";
+			arrow
+			(
+				angleStartCurrent,
+				angleEndCurrent,
+				radiusInner
+			);
+		}
+		else
+		{
+			drawWedge
+			(
+				angleStartCurrent,
+				angleEndCurrent,
+				radiusInner,
+				gRadius,
+				highlightFill,
+				0,
+				true
+			);
+		}
+		
+		// check if hidden children should be highlighted
+		//
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			if
+			(
+				this.children[i].getDepth() - selectedNode.getDepth() + 1 <=
+				maxDisplayDepth &&
+				this.children[i].hiddenEnd != null
+			)
+			{
+				var firstChild = this.children[i];
+				var lastChild = this.children[firstChild.hiddenEnd];
+				var hiddenAngleStart = firstChild.angleStart.current() + rotationOffset;
+				var hiddenAngleEnd = lastChild.angleEnd.current() + rotationOffset;
+				var hiddenRadiusInner = gRadius * firstChild.radiusInner.current();
+				
+				drawWedge
+				(
+					hiddenAngleStart,
+					hiddenAngleEnd,
+					hiddenRadiusInner,
+					gRadius,
+					'rgba(255, 255, 255, .3)',
+					0,
+					true
+				);
+				
+				if ( ! this.searchResults )
+				{
+					this.drawHiddenLabel
+					(
+						hiddenAngleStart,
+						hiddenAngleEnd,
+						firstChild.hiddenEnd - i + 1
+					);
+				}
+				
+				i = firstChild.hiddenEnd;
+			}
+		}
+		
+//			context.strokeStyle = 'black';
+		context.fillStyle = 'black';
+		
+		var highlight = ! ( progress < 1 && zoomOut && this == selectedNodeLast );
+		
+		var angle = (angleEndCurrent + angleStartCurrent) / 2;
+		
+		if ( ! (this.keyed && showKeys) )
+		{
+			this.drawLabel(angle, true, bold, true, this.radial);
+		}
+	}
+	
+	this.drawHighlightCenter = function()
+	{
+		if ( ! this.canDisplayHistory() )
+		{
+			return;
+		}
+		
+		context.lineWidth = highlightLineWidth;
+		context.strokeStyle = 'black';
+		context.fillStyle = "rgba(255, 255, 255, .6)";
+		
+		context.fillStyle = 'black';
+		this.drawLabel(3 * Math.PI / 2, true, true, false);
+		context.font = fontNormal;
+	}
+	
+	this.drawKey = function(angle, highlight, bold)
+	{
+		var offset = keyOffset();
+		var color;
+		var patternAlpha = this.alphaPattern.end;
+		var boxLeft = imageWidth - keySize - margin;
+		var textY = offset + keySize / 2;
+		
+		var label;
+		var keyNameWidth;
+		
+		if ( this == selectedNode )
+		{
+			color = colorUnclassified;
+			label =
+				this.getUnclassifiedText() +
+				'   ' +
+				this.getUnclassifiedPercentage();
+			keyNameWidth = measureText(label, false);
+		}
+		else
+		{
+			label = this.keyLabel;
+			color = rgbText(this.r.end, this.g.end, this.b.end);
+			
+			if ( highlight )
+			{
+				if ( this.searchResultChildren() )
+				{
+					label = label + searchResultString(this.searchResultChildren());
+				}
+				
+				keyNameWidth = measureText(label, bold);
+			}
+			else
+			{
+				keyNameWidth = this.keyNameWidth;
+			}
+		}
+		
+		var textLeft = boxLeft - keyBuffer - keyNameWidth - fontSize / 2;
+		var labelLeft = textLeft;
+		
+		if ( labelLeft > keyMinTextLeft - fontSize / 2 )
+		{
+			keyMinTextLeft -= fontSize / 2;
+			
+			if ( keyMinTextLeft < centerX - gRadius + fontSize / 2 )
+			{
+				keyMinTextLeft = centerX - gRadius + fontSize / 2;
+			}
+			
+			labelLeft = keyMinTextLeft;
+		}
+		
+		var lineX = new Array();
+		var lineY = new Array();
+		
+		var bendRadius;
+		var keyAngle = Math.atan((textY - centerY) / (labelLeft - centerX));
+		var arcAngle;
+		
+		if ( keyAngle < 0 )
+		{
+			keyAngle += Math.PI;
+		}
+		
+		if ( keyMinAngle == 0 || angle < keyMinAngle )
+		{
+			keyMinAngle = angle;
+		}
+		
+		if ( angle > Math.PI && keyMinAngle > Math.PI )
+		{
+			// allow lines to come underneath the chart
+			
+			angle -= Math.PI * 2;
+		}
+		
+		lineX.push(Math.cos(angle) * gRadius);
+		lineY.push(Math.sin(angle) * gRadius);
+		
+		if ( angle < keyAngle && textY > centerY + Math.sin(angle) * (gRadius + buffer * (currentKey - 1) / (keys + 1) / 2 + buffer / 2) )
+		{
+			bendRadius = gRadius + buffer - buffer * currentKey / (keys + 1) / 2;
+		}
+		else
+		{
+			bendRadius = gRadius + buffer * currentKey / (keys + 1) / 2 + buffer / 2;
+		}
+		
+		var outside =
+			Math.sqrt
+			(
+				Math.pow(labelLeft - centerX, 2) +
+				Math.pow(textY - centerY, 2)
+			) > bendRadius;
+		
+		if ( ! outside )
+		{
+			arcAngle = Math.asin((textY - centerY) / bendRadius);
+			
+			keyMinTextLeft = min(keyMinTextLeft, centerX + bendRadius * Math.cos(arcAngle) - fontSize / 2);
+			
+			if ( labelLeft < textLeft && textLeft > centerX + bendRadius * Math.cos(arcAngle) )
+			{
+				lineX.push(textLeft - centerX);
+				lineY.push(textY - centerY);
+			}
+		}
+		else
+		{
+			keyMinTextLeft = min(keyMinTextLeft, labelLeft - fontSize / 2);
+			
+			if ( angle < keyAngle )
+			{
+				// flip everything over y = x
+				//
+				arcAngle = Math.PI / 2 - keyLineAngle
+				(
+					Math.PI / 2 - angle,
+					Math.PI / 2 - keyAngle,
+					bendRadius,
+					textY - centerY,
+					labelLeft - centerX,
+					lineY,
+					lineX
+				);
+				
+			}
+			else
+			{
+				arcAngle = keyLineAngle
+				(
+					angle,
+					keyAngle,
+					bendRadius,
+					labelLeft - centerX,
+					textY - centerY,
+					lineX,
+					lineY
+				);
+			}
+		}
+		
+		if ( labelLeft > centerX + bendRadius * Math.cos(arcAngle) ||
+		textY > centerY + bendRadius * Math.sin(arcAngle) + .01)
+//		if ( outside ||  )
+		{
+			lineX.push(labelLeft - centerX);
+			lineY.push(textY - centerY);
+			
+			if ( textLeft != labelLeft )
+			{
+				lineX.push(textLeft - centerX);
+				lineY.push(textY - centerY);
+			}
+		}
+		
+		context.globalAlpha = this.alphaWedge.current();
+		
+		if ( snapshotMode )
+		{
+			var labelSVG;
+			
+			if ( this == selectedNode )
+			{
+				labelSVG =
+					this.getUnclassifiedText() +
+					spacer() +
+					this.getUnclassifiedPercentage();
+			}
+			else
+			{
+				labelSVG = this.name + spacer() + this.getPercentage() + '%';
+			}
+			
+			svg +=
+				'<rect fill="' + color + '" ' +
+				'x="' + boxLeft + '" y="' + offset +
+				'" width="' + keySize + '" height="' + keySize + '"/>';
+			
+			if ( patternAlpha )
+			{
+				svg +=
+					'<rect fill="url(#hiddenPattern)" style="stroke:none" ' +
+					'x="' + boxLeft + '" y="' + offset +
+					'" width="' + keySize + '" height="' + keySize + '"/>';
+			}
+			
+			svg +=
+				'<path class="line' +
+				(highlight ? ' highlight' : '') +
+				'" d="M ' + (lineX[0] + centerX) + ',' +
+				(lineY[0] + centerY);
+			
+			if ( angle != arcAngle )
+			{
+				svg +=
+					' L ' + (centerX + bendRadius * Math.cos(angle)) + ',' +
+					(centerY + bendRadius * Math.sin(angle)) +
+					' A ' + bendRadius + ',' + bendRadius + ' 0 ' +
+					'0,' + (angle > arcAngle ? '0' : '1') + ' ' +
+					(centerX + bendRadius * Math.cos(arcAngle)) + ',' +
+					(centerY + bendRadius * Math.sin(arcAngle));
+			}
+			
+			for ( var i = 1; i < lineX.length; i++ )
+			{
+				svg +=
+					' L ' + (centerX + lineX[i]) + ',' +
+					(centerY + lineY[i]);
+			}
+			
+			svg += '"/>';
+			
+			if ( highlight )
+			{
+				if ( this.searchResultChildren() )
+				{
+					labelSVG = labelSVG + searchResultString(this.searchResultChildren());
+				}
+				
+				drawBubbleSVG
+				(
+					boxLeft - keyBuffer - keyNameWidth - fontSize / 2,
+					textY - fontSize,
+					keyNameWidth + fontSize,
+					fontSize * 2,
+					fontSize,
+					0
+				);
+				
+				if ( this.isSearchResult )
+				{
+					drawSearchHighlights
+					(
+						label,
+						boxLeft - keyBuffer - keyNameWidth,
+						textY,
+						0
+					)
+				}
+			}
+			
+			svg += svgText(labelSVG, boxLeft - keyBuffer, textY, 'end', bold);
+		}
+		else
+		{
+			context.fillStyle = color;
+			context.translate(-centerX, -centerY);
+			context.strokeStyle = 'black';
+				context.globalAlpha = 1;//this.alphaWedge.current();
+			
+			context.fillRect(boxLeft, offset, keySize, keySize);
+			
+			if ( patternAlpha )
+			{
+				context.globalAlpha = patternAlpha;
+				context.fillStyle = hiddenPattern;
+				
+				// make clipping box for Firefox performance
+				context.beginPath();
+				context.moveTo(boxLeft, offset);
+				context.lineTo(boxLeft + keySize, offset);
+				context.lineTo(boxLeft + keySize, offset + keySize);
+				context.lineTo(boxLeft, offset + keySize);
+				context.closePath();
+				context.save();
+				context.clip();
+				
+				context.fillRect(boxLeft, offset, keySize, keySize);
+				context.fillRect(boxLeft, offset, keySize, keySize);
+				
+				context.restore(); // remove clipping region
+			}
+			
+			if ( highlight )
+			{
+				this.setHighlightStyle();
+				context.fillRect(boxLeft, offset, keySize, keySize);
+			}
+			else
+			{
+				context.lineWidth = thinLineWidth;
+			}
+			
+			context.strokeRect(boxLeft, offset, keySize, keySize);
+			
+			if ( lineX.length )
+			{
+				context.beginPath();
+				context.moveTo(lineX[0] + centerX, lineY[0] + centerY);
+				
+				context.arc(centerX, centerY, bendRadius, angle, arcAngle, angle > arcAngle);
+				
+				for ( var i = 1; i < lineX.length; i++ )
+				{
+					context.lineTo(lineX[i] + centerX, lineY[i] + centerY);
+				}
+				
+				context.globalAlpha = this == selectedNode ?
+					this.children[0].alphaWedge.current() :
+					this.alphaWedge.current();
+				context.lineWidth = highlight ? highlightLineWidth : thinLineWidth;
+				context.stroke();
+				context.globalAlpha = 1;
+			}
+			
+			if ( highlight )
+			{
+				drawBubbleCanvas
+				(
+					boxLeft - keyBuffer - keyNameWidth - fontSize / 2,
+					textY - fontSize,
+					keyNameWidth + fontSize,
+					fontSize * 2,
+					fontSize,
+					0
+				);
+				
+				if ( this.isSearchResult )
+				{
+					drawSearchHighlights
+					(
+						label,
+						boxLeft - keyBuffer - keyNameWidth,
+						textY,
+						0
+					)
+				}
+			}
+			
+			drawText(label, boxLeft - keyBuffer, offset + keySize / 2, 0, 'end', bold);
+			
+			context.translate(centerX, centerY);
+		}
+		
+		currentKey++;
+	}
+	
+	this.drawLabel = function(angle, bubble, bold, selected, radial)
+	{
+		if ( context.globalAlpha == 0 )
+		{
+			return;
+		}
+		
+		var innerText;
+		var label;
+		var radius;
+		
+		if ( radial )
+		{
+			radius = (this.radiusInner.current() + 1) * gRadius / 2;
+		}
+		else
+		{
+			radius = this.labelRadius.current() * gRadius;
+		}
+		
+		if ( radial && (selected || bubble ) )
+		{
+			var percentage = this.getPercentage();
+			innerText = percentage + '%';
+		}
+		
+		if
+		(
+			! radial &&
+			this != selectedNode &&
+			! bubble &&
+			( !zoomOut || this != selectedNodeLast)
+		)
+		{
+			label = this.shortenLabel();
+		}
+		else
+		{
+			label = this.name;
+		}
+		
+		var flipped = drawTextPolar
+		(
+			label,
+			innerText,
+			angle,
+			radius,
+			radial,
+			bubble,
+			bold,
+//			this.isSearchResult && this.shouldAddSearchResultsString() && (!selected || this == selectedNode || highlight),
+			this.isSearchResult && (!selected || this == selectedNode || bubble),
+			(this.hideAlone || !selected || this == selectedNode ) ? this.searchResultChildren() : 0
+		);
+		
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		
+		if
+		(
+			! radial &&
+			! bubble &&
+			this != selectedNode &&
+			this.angleEnd.end != this.angleStart.end &&
+			nLabelOffsets[depth - 2] > 2 &&
+			this.labelWidth.current() > (this.angleEnd.end - this.angleStart.end) * Math.abs(radius) &&
+			! ( zoomOut && this == selectedNodeLast ) &&
+			this.labelRadius.end > 0
+		)
+		{
+			// name extends beyond wedge; draw tick mark towards the central
+			// radius for easier identification
+			
+			var radiusCenter = compress ?
+				(compressedRadii[depth - 1] + compressedRadii[depth - 2]) / 2 :
+				(depth - .5) * nodeRadius;
+			
+			if ( this.labelRadius.end > radiusCenter )
+			{
+				if ( flipped )
+				{
+					drawTick(radius - tickLength * 1.4 , tickLength, angle);
+				}
+				else
+				{
+					drawTick(radius - tickLength * 1.7, tickLength, angle);
+				}
+			}
+			else
+			{
+				if ( flipped )
+				{
+					drawTick(radius + tickLength * .7, tickLength, angle);
+				}
+				else
+				{
+					drawTick(radius + tickLength * .4, tickLength, angle);
+				}
+			}
+		}
+	}
+	
+	this.drawLines = function(angleStart, angleEnd, radiusInner, drawRadial, selected)
+	{
+		if ( snapshotMode )
+		{
+			if ( this != selectedNode)
+			{
+				if ( angleEnd == angleStart + Math.PI * 2 )
+				{
+					// fudge to prevent overlap, which causes arc ambiguity
+					//
+					angleEnd -= .1 / gRadius;
+				}
+				
+				var longArc = angleEnd - angleStart > Math.PI ? 1 : 0;
+				
+				var x1 = centerX + radiusInner * Math.cos(angleStart);
+				var y1 = centerY + radiusInner * Math.sin(angleStart);
+				
+				var x2 = centerX + gRadius * Math.cos(angleStart);
+				var y2 = centerY + gRadius * Math.sin(angleStart);
+				
+				var x3 = centerX + gRadius * Math.cos(angleEnd);
+				var y3 = centerY + gRadius * Math.sin(angleEnd);
+				
+				var x4 = centerX + radiusInner * Math.cos(angleEnd);
+				var y4 = centerY + radiusInner * Math.sin(angleEnd);
+				
+				if ( this.alphaArc.end )
+				{
+					var dArray =
+					[
+						" M ", x4, ",", y4,
+						" A ", radiusInner, ",", radiusInner, " 0 ", longArc,
+							" 0 ", x1, ",", y1
+					];
+					
+					svg += '<path class="line" d="' + dArray.join('') + '"/>';
+				}
+				
+				if ( drawRadial && this.alphaLine.end )
+				{
+					svg += '<line x1="' + x3 + '" y1="' + y3 + '" x2="' + x4 + '" y2="' + y4 + '"/>';
+				}
+			}
+		}
+		else
+		{
+			context.lineWidth = thinLineWidth;
+			context.strokeStyle = 'black';
+			context.beginPath();
+			context.arc(0, 0, radiusInner, angleStart, angleEnd, false);
+			context.globalAlpha = this.alphaArc.current();
+			context.stroke();
+			
+			if ( drawRadial )
+			{
+				var x1 = radiusInner * Math.cos(angleEnd);
+				var y1 = radiusInner * Math.sin(angleEnd);
+				var x2 = gRadius * Math.cos(angleEnd);
+				var y2 = gRadius * Math.sin(angleEnd);
+				
+				context.beginPath();
+				context.moveTo(x1, y1);
+				context.lineTo(x2, y2);
+				
+//				if ( this.getCollapse() )//( selected && this != selectedNode )
+				{
+					context.globalAlpha = this.alphaLine.current();
+				}
+				
+				context.stroke();
+			}
+		}
+	}
+	
+	this.drawMap = function(child)
+	{
+		if ( this.parent )
+		{
+			this.parent.drawMap(child);
+		}
+		
+		if ( this.getCollapse() && this != child || this == focusNode )
+		{
+			return;
+		}
+		
+		var angleStart =
+			(child.baseMagnitude - this.baseMagnitude) / this.magnitude * Math.PI * 2 +
+			rotationOffset;
+		var angleEnd =
+			(child.baseMagnitude - this.baseMagnitude + child.magnitude) /
+			this.magnitude * Math.PI * 2 +
+			rotationOffset;
+		
+		var box = this.getMapPosition();
+		
+		context.save();
+		context.fillStyle = 'black';
+		context.textAlign = 'end';
+		context.textBaseline = 'middle';
+		
+		var textX = box.x - mapRadius - mapBuffer;
+		var percentage = getPercentage(child.magnitude / this.magnitude);
+		
+		var highlight = this == selectedNode || this == highlightedNode;
+		
+		if ( highlight )
+		{
+			context.font = fontBold;
+		}
+		else
+		{
+			context.font = fontNormal;
+		}
+		
+		context.fillText(percentage + '% of', textX, box.y - mapRadius / 3);
+		context.fillText(this.name, textX, box.y + mapRadius / 3);
+		
+		if ( highlight )
+		{
+			context.font = fontNormal;
+		}
+		
+		if ( this == highlightedNode && this != selectedNode )
+		{
+			context.fillStyle = 'rgb(245, 245, 245)';
+//			context.fillStyle = 'rgb(200, 200, 200)';
+		}
+		else
+		{
+			context.fillStyle = 'rgb(255, 255, 255)';
+		}
+		
+		context.beginPath();
+		context.arc(box.x, box.y, mapRadius, 0, Math.PI * 2, true);
+		context.closePath();
+		context.fill();
+		
+		if ( this == selectedNode )
+		{
+			context.lineWidth = 1;
+			context.fillStyle = 'rgb(100, 100, 100)';
+		}
+		else
+		{
+			if ( this == highlightedNode )
+			{
+				context.lineWidth = .2;
+				context.fillStyle = 'rgb(190, 190, 190)';
+			}
+			else
+			{
+				context.lineWidth = .2;
+				context.fillStyle = 'rgb(200, 200, 200)';
+			}
+		}
+		
+		var maxDepth = this.getMaxDepth();
+		
+		if ( ! compress && maxDepth > maxPossibleDepth + this.getDepth() - 1 )
+		{
+			maxDepth = maxPossibleDepth + this.getDepth() - 1;
+		}
+		
+		if ( this.getDepth() < selectedNode.getDepth() )
+		{
+			if ( child.getDepth() - 1 >= maxDepth )
+			{
+				maxDepth = child.getDepth();
+			}
+		}
+		
+		var radiusInner;
+		
+		if ( compress )
+		{
+			radiusInner = 0;
+//				Math.atan(child.getDepth() - this.getDepth()) /
+//				Math.PI * 2 * .9;
+		}
+		else
+		{
+			radiusInner =
+				(child.getDepth() - this.getDepth()) /
+				(maxDepth - this.getDepth() + 1);
+		}
+		
+		context.stroke();
+		context.beginPath();
+		
+		if ( radiusInner == 0 )
+		{
+			context.moveTo(box.x, box.y);
+		}
+		else
+		{
+			context.arc(box.x, box.y, mapRadius * radiusInner, angleEnd, angleStart, true);
+		}
+		
+		context.arc(box.x, box.y, mapRadius, angleStart, angleEnd, false);
+		context.closePath();
+		context.fill();
+		
+		if ( this == highlightedNode && this != selectedNode )
+		{
+			context.lineWidth = 1;
+			context.stroke();
+		}
+		
+		context.restore();
+	}
+	
+	this.drawReferenceRings = function(childRadiusInner)
+	{
+		if ( snapshotMode )
+		{
+			svg +=
+				'<circle cx="' + centerX + '" cy="' + centerY +
+				'" r="' + childRadiusInner + '"/>';
+			svg +=
+				'<circle cx="' + centerX + '" cy="' + centerY +
+				'" r="' + gRadius + '"/>';
+		}
+		else
+		{
+			context.globalAlpha = 1 - this.alphaLine.current();//this.getUncollapsed().alphaLine.current();
+			context.beginPath();
+			context.arc(0, 0, childRadiusInner, 0, Math.PI * 2, false);
+			context.stroke();
+			context.beginPath();
+			context.arc(0, 0, gRadius, 0, Math.PI * 2, false);
+			context.stroke();
+		}
+	}
+	
+	this.getCollapse = function()
+	{
+		return (
+			collapse &&
+			this.collapse &&
+			this.depth != maxAbsoluteDepth
+			);
+	}
+	
+	this.getDepth = function()
+	{
+		if ( collapse )
+		{
+			return this.depthCollapsed;
+		}
+		else
+		{
+			return this.depth;
+		}
+	}
+	
+	this.getMagnitude = function()
+	{
+		return this.attributes[magnitudeIndex][currentDataset];
+	}
+	
+	this.getMapPosition = function()
+	{
+		return {
+			x : (details.offsetLeft + details.clientWidth - mapRadius),
+			y : ((focusNode.getDepth() - this.getDepth()) *
+				(mapBuffer + mapRadius * 2) - mapRadius) +
+				details.clientHeight + details.offsetTop
+		};
+	}
+	
+	this.getMaxDepth = function(limit)
+	{
+		var max;
+		
+		if ( collapse )
+		{
+			return this.maxDepthCollapsed;
+		}
+		else
+		{
+			if ( this.maxDepth > maxAbsoluteDepth )
+			{
+				return maxAbsoluteDepth;
+			}
+			else
+			{
+				return this.maxDepth;
+			}
+		}
+	}
+	
+	this.getMembers = function()
+	{
+		var totalMembers = new Array();
+		
+		if ( this.members )
+		{
+			totalMembers = totalMembers.concat(this.members);
+		}
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			totalMembers = totalMembers.concat(this.children[i].getMembers());
+		}
+		
+		return totalMembers;
+	}
+	
+	this.getParent = function()
+	{
+		// returns parent, accounting for collapsing or 0 if doesn't exist
+		
+		var parent = this.parent;
+		
+		while ( parent != 0 && parent.getCollapse() )
+		{
+			parent = parent.parent;
+		}
+		
+		return parent;
+	}
+	
+	this.getPercentage = function()
+	{
+		return getPercentage(this.magnitude / selectedNode.magnitude);
+	}
+	
+	this.getUnclassifiedPercentage = function()
+	{
+		var lastChild = this.children[this.children.length - 1];
+		
+		return getPercentage
+		(
+			(
+				this.baseMagnitude +
+				this.magnitude -
+				lastChild.magnitude -
+				lastChild.baseMagnitude
+			) / this.magnitude
+		) + '%';
+	}
+	
+	this.getUnclassifiedText = function()
+	{
+		return '[unclassified '+ this.name + ']';
+	}
+	
+	this.getUncollapsed = function()
+	{
+		// recurse through collapsed children until uncollapsed node is found
+		
+		if ( this.getCollapse() )
+		{
+			return this.children[0].getUncollapsed();
+		}
+		else
+		{
+			return this;
+		}
+	}
+	
+	this.hasChildren = function()
+	{
+		return this.children.length && this.depth < maxAbsoluteDepth && this.magnitude;
+	}
+	
+	this.hasParent = function(parent)
+	{
+		if ( this.parent )
+		{
+			if ( this.parent == parent )
+			{
+				return true;
+			}
+			else
+			{
+				return this.parent.hasParent(parent);
+			}
+		}
+		else
+		{
+			return false;
+		}
+	}
+	
+	this.maxVisibleDepth = function(maxDepth)
+	{
+		var childInnerRadius;
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		var currentMaxDepth = depth;
+		
+		if ( this.hasChildren() && depth < maxDepth)
+		{
+			var lastChild = this.children[this.children.length - 1];
+			
+			if ( this.name == 'Pseudomonadaceae' )
+			{
+				var x = 3;
+			}
+			
+			if
+			(
+				lastChild.baseMagnitude + lastChild.magnitude <
+				this.baseMagnitude + this.magnitude
+			)
+			{
+				currentMaxDepth++;
+			}
+			
+			if ( compress )
+			{
+				childInnerRadius = compressedRadii[depth - 1];
+			}
+			else
+			{
+				childInnerRadius = (depth) / maxDepth;
+			}
+			
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				if
+				(//true ||
+					this.children[i].magnitude *
+					angleFactor *
+					(childInnerRadius + 1) *
+					gRadius >=
+					minWidth()
+				)
+				{
+					var childMaxDepth = this.children[i].maxVisibleDepth(maxDepth);
+					
+					if ( childMaxDepth > currentMaxDepth )
+					{
+						currentMaxDepth = childMaxDepth;
+					}
+				}
+			}
+		}
+		
+		return currentMaxDepth;
+	}
+	
+	this.resetLabelWidth = function()
+	{
+		var nameWidthOld = this.nameWidth;
+		
+		if ( ! this.radial )//&& fontSize != fontSizeLast )
+		{
+			var dim = context.measureText(this.name);
+			this.nameWidth = dim.width;
+		}
+		
+		if ( fontSize != fontSizeLast && this.labelWidth.end == nameWidthOld * labelWidthFudge )
+		{
+			// font size changed; adjust start of tween to match
+			
+			this.labelWidth.start = this.nameWidth * labelWidthFudge;
+		}
+		else
+		{
+			this.labelWidth.start = this.labelWidth.current();
+		}
+		
+		this.labelWidth.end = this.nameWidth * labelWidthFudge;
+	}
+	
+	this.restrictLabelWidth = function(width)
+	{
+		if ( width < this.labelWidth.end )
+		{
+			this.labelWidth.end = width;
+		}
+	}
+	
+	this.search = function()
+	{
+		this.isSearchResult = false;
+		this.searchResults = 0;
+		
+		if
+		(
+			! this.getCollapse() &&
+			search.value != '' &&
+			this.name.toLowerCase().indexOf(search.value.toLowerCase()) != -1
+		)
+		{
+			this.isSearchResult = true;
+			this.searchResults = 1;
+			nSearchResults++;
+		}
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.searchResults += this.children[i].search();
+		}
+		
+		return this.searchResults;
+	}
+	
+	this.searchResultChildren = function()
+	{
+		if ( this.isSearchResult )
+		{
+			return this.searchResults - 1;
+		}
+		else
+		{
+			return this.searchResults;
+		}
+	}
+	
+	this.setDepth = function(depth, depthCollapsed)
+	{
+		this.depth = depth;
+		this.depthCollapsed = depthCollapsed;
+		
+		if
+		(
+			this.children.length == 1 &&
+//			this.magnitude > 0 &&
+			this.children[0].magnitude == this.magnitude &&
+			( head.children.length > 1 || this.children[0].children.length )
+		)
+		{
+			this.collapse = true;
+		}
+		else
+		{
+			this.collapse = false;
+			depthCollapsed++;
+		}
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setDepth(depth + 1, depthCollapsed);
+		}
+	}
+	
+	this.setHighlightStyle = function()
+	{
+		context.lineWidth = highlightLineWidth;
+		
+		if ( this.hasChildren() || this != focusNode || this != highlightedNode )
+		{
+			context.strokeStyle = 'black';
+			context.fillStyle = "rgba(255, 255, 255, .3)";
+		}
+		else
+		{
+			context.strokeStyle = 'rgb(90,90,90)';
+			context.fillStyle = "rgba(155, 155, 155, .3)";
+		}
+	}
+	
+	this.setLabelWidth = function(node)
+	{
+		if ( ! shorten || this.radial )
+		{
+			return; // don't need to set width
+		}
+		
+		if ( node.hide )
+		{
+			alert('wtf');
+			return;
+		}
+		
+		var angle = (this.angleStart.end + this.angleEnd.end) / 2;
+		var a; // angle difference
+		
+		if ( node == selectedNode )
+		{
+			a = Math.abs(angle - node.angleOther);
+		}
+		else
+		{
+			a = Math.abs(angle - (node.angleStart.end + node.angleEnd.end) / 2);
+		}
+		
+		if ( a == 0 )
+		{
+			return;
+		}
+		
+		if ( a > Math.PI )
+		{
+			a = 2 * Math.PI - a;
+		}
+		
+		if ( node.radial || node == selectedNode )
+		{
+			var nodeLabelRadius;
+			
+			if ( node == selectedNode )
+			{
+				// radial 'other' label
+				
+				nodeLabelRadius = (node.children[0].radiusInner.end + 1) / 2;
+			}
+			else
+			{
+				nodeLabelRadius = (node.radiusInner.end + 1) / 2;
+			}
+			
+			if ( a < Math.PI / 2 )
+			{
+				var r = this.labelRadius.end * gRadius + .5 * fontSize
+				var hypotenuse = r / Math.cos(a);
+				var opposite = r * Math.tan(a);
+				var fontRadius = .8 * fontSize;
+				
+				if
+				(
+					nodeLabelRadius * gRadius < hypotenuse &&
+					this.labelWidth.end / 2 + fontRadius > opposite
+				)
+				{
+					this.labelWidth.end = 2 * (opposite - fontRadius);
+				}
+			}
+		}
+		else if
+		(
+			this.labelRadius.end == node.labelRadius.end &&
+			a < Math.PI / 4
+		)
+		{
+			// same radius with small angle; use circumferential approximation
+			
+			var dist = a * this.labelRadius.end * gRadius - fontSize * (1 - a * 4 / Math.PI) * 1.3;
+			
+			if ( this.labelWidth.end < dist )
+			{
+				node.restrictLabelWidth((dist - this.labelWidth.end / 2) * 2);
+			}
+			else if ( node.labelWidth.end < dist )
+			{
+				this.restrictLabelWidth((dist - node.labelWidth.end / 2) * 2);
+			}
+			else
+			{
+				// both labels reach halfway point; restrict both
+				
+				this.labelWidth.end = dist;
+				node.labelWidth.end = dist
+			}
+		}
+		else
+		{
+			var r1 = this.labelRadius.end * gRadius;
+			var r2 = node.labelRadius.end * gRadius;
+			
+			// first adjust the radii to account for the height of the font by shifting them
+			// toward each other
+			//
+			var fontFudge = .35 * fontSize;
+			//
+			if ( this.labelRadius.end < node.labelRadius.end )
+			{
+				r1 += fontFudge;
+				r2 -= fontFudge;
+			}
+			else if ( this.labelRadius.end > node.labelRadius.end )
+			{
+				r1 -= fontFudge;
+				r2 += fontFudge;
+			}
+			else
+			{
+				r1 -= fontFudge;
+				r2 -= fontFudge;
+			}
+			
+			var r1s = r1 * r1;
+			var r2s = r2 * r2;
+			
+			// distance between the centers of the two labels
+			//
+			var dist = Math.sqrt(r1s + r2s - 2 * r1 * r2 * Math.cos(a));
+			
+			// angle at our label center between our radius and the line to the other label center
+			//
+			var b = Math.acos((r1s + dist * dist - r2s) / (2 * r1 * dist));
+			
+			// distance from our label center to the intersection of the two tangents
+			//
+			var l1 = Math.sin(a + b - Math.PI / 2) * dist / Math.sin(Math.PI - a);
+			
+			// distance from other label center the the intersection of the two tangents
+			//
+			var l2 = Math.sin(Math.PI / 2 - b) * dist / Math.sin(Math.PI - a);
+			
+			l1 = Math.abs(l1) - .4 * fontSize;
+			l2 = Math.abs(l2) - .4 * fontSize;
+/*			
+			// amount to shorten the distances because of the height of the font
+			//
+			var l3 = 0;
+			var fontRadius = fontSize * .55;
+			//
+			if ( l1 < 0 || l2 < 0 )
+			{
+				var l4 = fontRadius / Math.tan(a);
+			l1 = Math.abs(l1);
+			l2 = Math.abs(l2);
+			
+				l1 -= l4;
+				l2 -= l4;
+			}
+			else
+			{
+				var c = Math.PI - a;
+				
+				l3 = fontRadius * Math.tan(c / 2);
+			}
+*/			
+			if ( this.labelWidth.end / 2 > l1 && node.labelWidth.end / 2 > l2 )
+			{
+				// shorten the farthest one from the intersection
+				
+				if ( l1 > l2 )
+				{
+					this.restrictLabelWidth(2 * (l1));// - l3 - fontRadius));
+				}
+				else
+				{
+					node.restrictLabelWidth(2 * (l2));// - l3 - fontRadius));
+				}
+			}/*
+			else if ( this.labelWidth.end / 2 > l1 + l3 && node.labelWidth.end / 2 > l2 - l3 )
+			{
+				node.restrictLabelWidth(2 * (l2 - l3));
+			}
+			else if ( this.labelWidth.end / 2 > l1 - l3 && node.labelWidth.end / 2 > l2 + l3 )
+			{
+				this.restrictLabelWidth(2 * (l1 - l3));
+			}*/
+		}
+	}
+	
+	this.setMagnitudes = function(baseMagnitude)
+	{
+		this.magnitude = this.getMagnitude();
+		this.baseMagnitude = baseMagnitude;
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setMagnitudes(baseMagnitude);
+			baseMagnitude += this.children[i].magnitude;
+		}
+		
+		this.maxChildMagnitude = baseMagnitude;
+	}
+	
+	this.setMaxDepths = function()
+	{
+		this.maxDepth = this.depth;
+		this.maxDepthCollapsed = this.depthCollapsed;
+		
+		for ( i in this.children )
+		{
+			var child = this.children[i];
+			
+			child.setMaxDepths();
+			
+			if ( child.maxDepth > this.maxDepth )
+			{
+				this.maxDepth = child.maxDepth;
+			}
+			
+			if
+			(
+				child.maxDepthCollapsed > this.maxDepthCollapsed &&
+				(child.depth <= maxAbsoluteDepth || maxAbsoluteDepth == 0)
+			)
+			{
+				this.maxDepthCollapsed = child.maxDepthCollapsed;
+			}
+		}
+	}
+	
+	this.setTargetLabelRadius = function()
+	{
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		var index = depth - 2;
+		var labelOffset = labelOffsets[index];
+		
+		if ( this.radial )
+		{
+			//this.labelRadius.setTarget((this.radiusInner.end + 1) / 2);
+			var max =
+				depth == maxDisplayDepth ?
+				1 :
+				compressedRadii[index + 1];
+			
+			this.labelRadius.setTarget((compressedRadii[index] + max) / 2);
+		}
+		else
+		{
+			var radiusCenter;
+			var width;
+			
+			if ( compress )
+			{
+				if ( nLabelOffsets[index] > 1 )
+				{
+					this.labelRadius.setTarget
+					(
+						lerp
+						(
+							labelOffset + .75,
+							0,
+							nLabelOffsets[index] + .5,
+							compressedRadii[index],
+							compressedRadii[index + 1]
+						)
+					);
+				}
+				else
+				{
+					this.labelRadius.setTarget((compressedRadii[index] + compressedRadii[index + 1]) / 2);
+				}
+			}
+			else
+			{
+				radiusCenter =
+					nodeRadius * (depth - 1) +
+					nodeRadius / 2;
+				width = nodeRadius;
+				
+				this.labelRadius.setTarget
+				(
+					radiusCenter + width * ((labelOffset + 1) / (nLabelOffsets[index] + 1) - .5)
+				);
+			}
+		}
+		
+		if ( ! this.hide && ! this.keyed && nLabelOffsets[index] )
+		{
+			// check last and first labels in each track for overlap
+			
+			for ( var i = 0; i < maxDisplayDepth - 1; i++ )
+			{
+				for ( var j = 0; j <= nLabelOffsets[i]; j++ )
+				{
+					var last = labelLastNodes[i][j];
+					var first = labelFirstNodes[i][j];
+					
+					if ( last )
+					{
+						if ( j == nLabelOffsets[i] )
+						{
+							// last is radial
+							this.setLabelWidth(last);
+						}
+						else
+						{
+							last.setLabelWidth(this);
+						}
+					}
+					
+					if ( first )
+					{
+						if ( j == nLabelOffsets[i] )
+						{
+							this.setLabelWidth(first);
+						}
+						else
+						{
+							first.setLabelWidth(this);
+						}
+					}
+				}
+			}
+			
+			if ( selectedNode.canDisplayLabelOther )
+			{
+				this.setLabelWidth(selectedNode); // in case there is an 'other' label
+			}
+			
+			if ( this.radial )
+			{
+				// use the last 'track' of this depth for radial
+				
+				labelLastNodes[index][nLabelOffsets[index]] = this;
+				
+				if ( labelFirstNodes[index][nLabelOffsets[index]] == 0 )
+				{
+					labelFirstNodes[index][nLabelOffsets[index]] = this;
+				}
+			}
+			else
+			{
+				labelLastNodes[index][labelOffset] = this;
+				
+				// update offset
+				
+				labelOffsets[index] += 1;
+				
+				if ( labelOffsets[index] > nLabelOffsets[index] )
+				{
+					labelOffsets[index] -= nLabelOffsets[index];
+					
+					if ( !(nLabelOffsets[index] & 1) )
+					{
+						labelOffsets[index]--;
+					}
+				}
+				else if ( labelOffsets[index] == nLabelOffsets[index] )
+				{
+					labelOffsets[index] -= nLabelOffsets[index];
+					
+					if ( false && !(nLabelOffsets[index] & 1) )
+					{
+						labelOffsets[index]++;
+					}
+				}
+				
+				if ( labelFirstNodes[index][labelOffset] == 0 )
+				{
+					labelFirstNodes[index][labelOffset] = this;
+				}
+			}
+		}
+		else if ( this.hide )
+		{
+			this.labelWidth.end = 0;
+		}
+	}
+	
+	this.setTargets = function()
+	{
+		if ( this == selectedNode )
+		{
+			this.setTargetsSelected
+			(
+				0,
+				1,
+				lightnessBase,
+				false,
+				false
+			);
+			return;
+		}
+		
+		var depthRelative = this.getDepth() - selectedNode.getDepth();
+		
+		var parentOfSelected = selectedNode.hasParent(this);
+/*		(
+//			! this.getCollapse() &&
+			this.baseMagnitude <= selectedNode.baseMagnitude &&
+			this.baseMagnitude + this.magnitude >=
+			selectedNode.baseMagnitude + selectedNode.magnitude
+		);
+*/		
+		if ( parentOfSelected )
+		{
+			this.resetLabelWidth();
+		}
+		else
+		{
+			//context.font = fontNormal;
+			var dim = context.measureText(this.name);
+			this.nameWidth = dim.width;
+			//this.labelWidth.setTarget(this.labelWidth.end);
+			this.labelWidth.setTarget(0);
+		}
+		
+		// set angles
+		//
+		if ( this.baseMagnitude <= selectedNode.baseMagnitude )
+		{
+			this.angleStart.setTarget(0);
+		}
+		else
+		{
+			this.angleStart.setTarget(Math.PI * 2);
+		}
+		//
+		if
+		(
+			parentOfSelected ||
+			this.baseMagnitude + this.magnitude >=
+			selectedNode.baseMagnitude + selectedNode.magnitude
+		)
+		{
+			this.angleEnd.setTarget(Math.PI * 2);
+		}
+		else
+		{
+			this.angleEnd.setTarget(0);
+		}
+		
+		// children
+		//
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setTargets();
+		}
+		
+		if ( this.getDepth() <= selectedNode.getDepth() )
+		{
+			// collapse in
+			
+			this.radiusInner.setTarget(0);
+			
+			if ( parentOfSelected )
+			{
+				this.labelRadius.setTarget
+				(
+					(depthRelative) *
+					historySpacingFactor * fontSize / gRadius
+				);
+				//this.scale.setTarget(1 - (selectedNode.getDepth() - this.getDepth()) / 18); // TEMP
+			}
+			else
+			{
+				this.labelRadius.setTarget(0);
+				//this.scale.setTarget(1); // TEMP
+			}
+		}
+		else if ( depthRelative + 1 > maxDisplayDepth )
+		{
+			// collapse out
+			
+			this.radiusInner.setTarget(1);
+			this.labelRadius.setTarget(1);
+			//this.scale.setTarget(1); // TEMP
+		}
+		else
+		{
+			// don't collapse
+			
+			if ( compress )
+			{
+				this.radiusInner.setTarget(compressedRadii[depthRelative - 1]);
+			}
+			else
+			{
+				this.radiusInner.setTarget(nodeRadius * (depthRelative));
+			}
+			
+			//this.scale.setTarget(1); // TEMP
+			
+			if ( this == selectedNode )
+			{
+				this.labelRadius.setTarget(0);
+			}
+			else
+			{
+				if ( compress )
+				{
+					this.labelRadius.setTarget
+					(
+						(compressedRadii[depthRelative - 1] + compressedRadii[depthRelative]) / 2
+					);
+				}
+				else
+				{
+					this.labelRadius.setTarget(nodeRadius * (depthRelative) + nodeRadius / 2);
+				}
+			}
+		}
+		
+//		this.r.start = this.r.end;
+//		this.g.start = this.g.end;
+//		this.b.start = this.b.end;
+		
+		this.r.setTarget(255);
+		this.g.setTarget(255);
+		this.b.setTarget(255);
+
+		this.alphaLine.setTarget(0);
+		this.alphaArc.setTarget(0);
+		this.alphaWedge.setTarget(0);
+		this.alphaPattern.setTarget(0);
+		this.alphaOther.setTarget(0);
+		
+		if ( parentOfSelected && ! this.getCollapse() )
+		{
+			var alpha =
+			(
+				1 -
+				(selectedNode.getDepth() - this.getDepth()) /
+				(Math.floor((compress ? compressedRadii[0] : nodeRadius) * gRadius / (historySpacingFactor * fontSize) - .5) + 1)
+			);
+			
+			if ( alpha < 0 )
+			{
+				alpha = 0;
+			}
+			
+			this.alphaLabel.setTarget(alpha);
+			this.radial = false;
+		}
+		else
+		{
+			this.alphaLabel.setTarget(0);
+		}
+		
+		this.hideAlonePrev = this.hideAlone;
+		this.hidePrev = this.hide;
+		
+		if ( parentOfSelected )
+		{
+			this.hideAlone = false;
+			this.hide = false;
+		}
+		
+		if ( this.getParent() == selectedNode.getParent() )
+		{
+			this.hiddenEnd = null;
+		}
+		
+		this.radialPrev = this.radial;
+	}
+	
+	this.setTargetsSelected = function(hueMin, hueMax, lightness, hide, nextSiblingHidden)
+	{
+		var collapse = this.getCollapse();
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		var canDisplayChildLabels = false;
+		var lastChild;
+		
+		if ( this.hasChildren() )//&& ! hide )
+		{
+			lastChild = this.children[this.children.length - 1];
+			this.hideAlone = true;
+		}
+		else
+		{
+			this.hideAlone = false;
+		}
+		
+		// set child wedges
+		//
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setTargetWedge();
+			
+			if
+			(
+				! this.children[i].hide &&
+				( collapse || depth < maxDisplayDepth ) &&
+				this.depth < maxAbsoluteDepth
+			)
+			{
+				canDisplayChildLabels = true;
+				this.hideAlone = false;
+			}
+		}
+		
+		if ( this == selectedNode || lastChild && lastChild.angleEnd.end < this.angleEnd.end - .01)
+		{
+			this.hideAlone = false;
+		}
+		
+		if ( this.hideAlonePrev == undefined )
+		{
+			this.hideAlonePrev = this.hideAlone;
+		}
+		
+		if ( this == selectedNode )
+		{
+			var otherArc = 
+				angleFactor *
+				(
+					this.baseMagnitude + this.magnitude -
+					lastChild.baseMagnitude - lastChild.magnitude
+				);
+			this.canDisplayLabelOther =
+				otherArc *
+				(this.children[0].radiusInner.end + 1) * gRadius >=
+				minWidth();
+			
+			this.keyUnclassified = false;
+			
+			if ( this.canDisplayLabelOther )
+			{
+				this.angleOther = Math.PI * 2 - otherArc / 2;
+			}
+			else if ( otherArc > 0.0000000001 )
+			{
+				this.keyUnclassified = true;
+				keys++;
+			}
+			
+			this.angleStart.setTarget(0);
+			this.angleEnd.setTarget(Math.PI * 2);
+			this.radiusInner.setTarget(0);
+			this.hidePrev = this.hide;
+			this.hide = false;
+			this.hideAlonePrev = this.hideAlone;
+			this.hideAlone = false;
+			this.keyed = false;
+		}
+		
+		if ( hueMax - hueMin > 1 / 12 )
+		{
+			hueMax = hueMin + 1 / 12;
+		}
+		
+		// set lightness
+		//
+		if ( ! ( hide || this.hideAlone ) )
+		{
+			if ( useHue() )
+			{
+				lightness = (lightnessBase + lightnessMax) / 2;
+			}
+			else
+			{
+				lightness = lightnessBase + (depth - 1) * lightnessFactor;
+				
+				if ( lightness > lightnessMax )
+				{
+					lightness = lightnessMax;
+				}
+			}
+		}
+		
+		if ( hide )
+		{
+			this.hide = true;
+		}
+		
+		if ( this.hidePrev == undefined )
+		{
+			this.hidePrev = this.hide;
+		}
+		
+		var hiddenStart = -1;
+		var hiddenHueNumer = 0;
+		var hiddenHueDenom = 0;
+		var i = 0;
+		
+		if ( ! this.hide )
+		{
+			this.hiddenEnd = null;
+		}
+		
+		while ( true )
+		{
+			if ( ! this.hideAlone && ! hide && ( i == this.children.length || ! this.children[i].hide ) )
+			{
+				// reached a non-hidden child or the end; set targets for
+				// previous group of hidden children (if any) using their
+				// average hue
+				
+				if ( hiddenStart != -1 )
+				{
+					var hiddenHue = hiddenHueDenom ? hiddenHueNumer / hiddenHueDenom : hueMin;
+					
+					for ( var j = hiddenStart; j < i; j++ )
+					{
+						this.children[j].setTargetsSelected
+						(
+							hiddenHue,
+							null,
+							lightness,
+							false,
+							j < i - 1
+						);
+						
+						this.children[j].hiddenEnd = null;
+					}
+					
+					this.children[hiddenStart].hiddenEnd = i - 1;
+				}
+			}
+			
+			if ( i == this.children.length )
+			{
+				break;
+			}
+			
+			var child = this.children[i];
+			var childHueMin;
+			var childHueMax;
+			
+			if ( this.magnitude > 0 && ! this.hide && ! this.hideAlone )
+			{
+				if ( useHue() )
+				{
+					childHueMin = child.hues[currentDataset];
+				}
+				else if ( this == selectedNode )
+				{
+					if ( this.children.length > 6 )
+					{
+						childHueMin = (1 - Math.pow(1 - i / this.children.length, 1.4)) * .95;
+						childHueMax = (1 - Math.pow(1 - (i + .35) / this.children.length, 1.4)) * .95;
+					}
+					else
+					{
+						childHueMin = i / this.children.length;
+						childHueMax = (i + .35) / this.children.length;
+					}
+				}
+				else
+				{
+					childHueMin = lerp
+					(
+						child.baseMagnitude,
+						this.baseMagnitude, 
+						this.baseMagnitude + this.magnitude,
+						hueMin,
+						hueMax
+					);
+					childHueMax = lerp
+					(
+						child.baseMagnitude + child.magnitude * .7,
+						this.baseMagnitude,
+						this.baseMagnitude + this.magnitude,
+						hueMin,
+						hueMax
+					);
+				}
+			}
+			else
+			{
+				childHueMin = hueMin;
+				childHueMax = hueMax;
+			}
+			
+			if ( ! this.hideAlone && ! hide && ! this.hide && child.hide )
+			{
+				if ( hiddenStart == -1 )
+				{
+					hiddenStart = i;
+				}
+				
+				if ( useHue() )
+				{
+					hiddenHueNumer += childHueMin * child.magnitude;
+					hiddenHueDenom += child.magnitude;
+				}
+				else
+				{
+					hiddenHueNumer += childHueMin;
+					hiddenHueDenom++;
+				}
+			}
+			else
+			{
+				hiddenStart = -1;
+				
+				this.children[i].setTargetsSelected
+				(
+					childHueMin,
+					childHueMax,
+					lightness,
+					hide || this.keyed || this.hideAlone || this.hide && ! collapse,
+					false
+				);
+			}
+			
+			i++;
+		}
+		
+	 	if ( this.hues && this.magnitude )
+	 	{
+		 	this.hue.setTarget(this.hues[currentDataset]);
+			
+			if ( this.attributes[magnitudeIndex][lastDataset] == 0 )
+			{
+				this.hue.start = this.hue.end;
+			}
+		}
+	 	
+		this.radialPrev = this.radial;
+		
+		if ( this == selectedNode )
+		{
+			this.resetLabelWidth();
+			this.labelWidth.setTarget(this.nameWidth * labelWidthFudge);
+			this.alphaWedge.setTarget(0);
+			this.alphaLabel.setTarget(1);
+			this.alphaOther.setTarget(1);
+			this.alphaArc.setTarget(0);
+			this.alphaLine.setTarget(0);
+			this.alphaPattern.setTarget(0);
+			this.r.setTarget(255);
+			this.g.setTarget(255);
+			this.b.setTarget(255);
+			this.radial = false;
+			this.labelRadius.setTarget(0);
+		}
+		else
+		{
+			var rgb = hslToRgb
+			(
+				hueMin,
+				saturation,
+				lightness
+			);
+			
+			this.r.setTarget(rgb.r);
+			this.g.setTarget(rgb.g);
+			this.b.setTarget(rgb.b);
+			this.alphaOther.setTarget(0);
+			
+			this.alphaWedge.setTarget(1);
+			
+			if ( this.hide || this.hideAlone )
+			{
+				this.alphaPattern.setTarget(1);
+			}
+			else
+			{
+				this.alphaPattern.setTarget(0);
+			}
+			
+			// set radial
+			//
+			if ( ! ( hide || this.hide ) )//&& ! this.keyed )
+			{
+				if ( this.hideAlone )
+				{
+					this.radial = true;
+				}
+				else if ( false && canDisplayChildLabels )
+				{
+					this.radial = false;
+				}
+				else
+				{
+					this.radial = true;
+					
+					if ( this.hasChildren() && depth < maxDisplayDepth )
+					{
+						var lastChild = this.children[this.children.length - 1];
+						
+						if
+						(
+							lastChild.angleEnd.end == this.angleEnd.end ||
+							(
+								(this.angleStart.end + this.angleEnd.end) / 2 -
+								lastChild.angleEnd.end
+							) * (this.radiusInner.end + 1) * gRadius * 2 <
+							minWidth()
+						)
+						{
+							this.radial = false;
+						}
+					}
+				}
+			}
+			
+			// set alphaLabel
+			//
+			if
+			(
+				collapse ||
+				hide ||
+				this.hide ||
+				this.keyed ||
+				depth > maxDisplayDepth ||
+				! this.canDisplayDepth()
+			)
+			{
+				this.alphaLabel.setTarget(0);
+			}
+			else
+			{
+				if
+				(
+					(this.radial || nLabelOffsets[depth - 2])
+				)
+				{
+					this.alphaLabel.setTarget(1);
+				}
+				else
+				{
+					this.alphaLabel.setTarget(0);
+					
+					if ( this.radialPrev )
+					{
+						this.alphaLabel.start = 0;
+					}
+				}
+			}
+			
+			// set alphaArc
+			//
+			if
+			(
+				collapse ||
+				hide ||
+				depth > maxDisplayDepth ||
+				! this.canDisplayDepth()
+			)
+			{
+				this.alphaArc.setTarget(0);
+			}
+			else
+			{
+				this.alphaArc.setTarget(1);
+			}
+			
+			// set alphaLine
+			//
+			if
+			(
+				hide ||
+				this.hide && nextSiblingHidden ||
+				depth > maxDisplayDepth ||
+				! this.canDisplayDepth()
+			)
+			{
+				this.alphaLine.setTarget(0);
+			}
+			else
+			{
+				this.alphaLine.setTarget(1);
+			}
+			
+			//if (  ! this.radial )
+			{
+				this.resetLabelWidth();
+			}
+			
+			// set labelRadius target
+			//
+			if ( collapse )
+			{
+				this.labelRadius.setTarget(this.radiusInner.end);
+			}
+			else
+			{
+				if ( depth > maxDisplayDepth || ! this.canDisplayDepth() )
+				{
+					this.labelRadius.setTarget(1);
+				}
+				else
+				{
+					this.setTargetLabelRadius();
+				}
+			}
+		}
+	}
+	
+	this.setTargetWedge = function()
+	{
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		
+		// set angles
+		//
+		var baseMagnitudeRelative = this.baseMagnitude - selectedNode.baseMagnitude;
+		//
+		this.angleStart.setTarget(baseMagnitudeRelative * angleFactor);
+		this.angleEnd.setTarget((baseMagnitudeRelative + this.magnitude) * angleFactor);
+		
+		// set radiusInner
+		//
+		if ( depth > maxDisplayDepth || ! this.canDisplayDepth() )
+		{
+			this.radiusInner.setTarget(1);
+		}
+		else
+		{
+			if ( compress )
+			{
+				this.radiusInner.setTarget(compressedRadii[depth - 2]);
+			}
+			else
+			{
+				this.radiusInner.setTarget(nodeRadius * (depth - 1));
+			}
+		}
+		
+		if ( this.hide != undefined )
+		{
+			this.hidePrev = this.hide;
+		}
+		
+		if ( this.hideAlone != undefined )
+		{
+			this.hideAlonePrev = this.hideAlone;
+		}
+		
+		// set hide
+		//
+		if
+		(
+			(this.angleEnd.end - this.angleStart.end) *
+			(this.radiusInner.end * gRadius + gRadius) <
+			minWidth()
+		)
+		{
+			if ( depth == 2 && ! this.getCollapse() && this.depth <= maxAbsoluteDepth )
+			{
+				this.keyed = true;
+				keys++;
+				this.hide = false;
+				
+				var percentage = this.getPercentage();
+				this.keyLabel = this.name + '   ' + percentage + '%';
+				var dim = context.measureText(this.keyLabel);
+				this.keyNameWidth = dim.width;
+			}
+			else
+			{
+				this.keyed = false;
+				this.hide = depth > 2;
+			}
+		}
+		else
+		{
+			this.keyed = false;
+			this.hide = false;
+		}
+	}
+	
+	this.shortenLabel = function()
+	{
+		var label = this.name;
+		
+		var labelWidth = this.nameWidth;
+		var maxWidth = this.labelWidth.current();
+		var minEndLength = 0;
+		
+		if ( labelWidth > maxWidth && label.length > minEndLength * 2 )
+		{
+			var endLength =
+				Math.floor((label.length - 1) * maxWidth / labelWidth / 2);
+			
+			if ( endLength < minEndLength )
+			{
+				endLength = minEndLength;
+			}
+			
+			return (
+				label.substring(0, endLength) +
+				'...' +
+				label.substring(label.length - endLength));
+		}
+		else
+		{
+			return label;
+		}
+	}
+	
+/*	this.shouldAddSearchResultsString = function()
+	{
+		if ( this.isSearchResult )
+		{
+			return this.searchResults > 1;
+		}
+		else
+		{
+			return this.searchResults > 0;
+		}
+	}
+*/	
+	this.sort = function()
+	{
+		this.children.sort(function(a, b){return b.getMagnitude() - a.getMagnitude()});
+		
+		for (var i = 0; i < this.children.length; i++)
+		{
+			this.children[i].sort();
+		}
+	}
+}
+
+function addOptionElement(position, innerHTML, title)
+{
+	var div = document.createElement("div");
+	div.style.position = 'absolute';
+	div.style.top = position + 'px';
+	div.innerHTML = innerHTML;
+	
+	if ( title )
+	{
+		div.title = title;
+	}
+	
+	document.body.insertBefore(div, canvas);
+	return position + div.clientHeight;
+}
+
+function addOptionElements(hueName, hueDefault)
+{
+	document.body.style.font = '11px sans-serif';
+	var position = 5;
+	
+	document.getElementById('details').innerHTML = '\
+<span id="detailsName" style="font-weight:bold"></span> \
+<input type="button" id="detailsExpand" onclick="expand(focusNode);"\
+value="↔" title="Expand this wedge to become the new focus of the chart"/><br/>\
+<div id="detailsInfo" style="float:right"></div>';
+
+	keyControl = document.createElement('input');
+	keyControl.type = 'button';
+	keyControl.value = showKeys ? 'x' : '…';
+	keyControl.style.position = '';
+	keyControl.style.position = 'fixed';
+	keyControl.style.visibility = 'hidden';
+	
+	document.body.insertBefore(keyControl, canvas);
+	
+//	document.getElementById('options').style.fontSize = '9pt';
+	position = addOptionElement
+	(
+		position,
+' <input type="button" id="back" value="←" title="Go back (Shortcut: ←)"/>\
+<input type="button" id="forward" value="→" title="Go forward (Shortcut: →)"/> \
+ Search: <input type="text" id="search"/>\
+<input type="button" value="x" onclick="clearSearch()"/> \
+<span id="searchResults"></span>'
+	);
+	
+	if ( datasets > 1 )
+	{
+		var size = datasets < datasetSelectSize ? datasets : datasetSelectSize;
+		
+		var select =
+			'<div style="float:left"> </div><div style="float:left">' +
+			'<select id="datasets" style="width:' + datasetSelectWidth +
+			'px"' + 'size="' + size + '" onchange="onDatasetChange()">';
+		
+		for ( var i = 0; i < datasetNames.length; i++ )
+		{
+			select += '<option>' + datasetNames[i] + '</option>';
+		}
+		
+		select +=
+			'</select></div>' +
+			'<input title="Previous dataset (Shortcut: ↑)" id="prevDataset" type="button" value="↑" onclick="prevDataset()" disabled="true"/>' +
+			'<input title="Switch to the last dataset that was viewed (Shortcut: TAB)" id="lastDataset" type="button" style="font:11px Times new roman" value="last" onclick="selectLastDataset()"/>' +
+			'<br/><input title="Next dataset (Shortcut: ↓)" id="nextDataset" type="button" value="↓" onclick="nextDataset()"/><br/>';
+		
+		position = addOptionElement(position + 5, select);
+		
+		datasetDropDown = document.getElementById('datasets');
+		datasetButtonLast = document.getElementById('lastDataset');
+		datasetButtonPrev = document.getElementById('prevDataset');
+		datasetButtonNext = document.getElementById('nextDataset');
+	}
+	
+	position = addOptionElement
+	(
+		position + 5,
+' <input type="button" id="maxAbsoluteDepthDecrease" value="-"/>\
+<span id="maxAbsoluteDepth"></span>\
+ <input type="button" id="maxAbsoluteDepthIncrease" value="+"/> Max depth',
+'Maximum depth to display, counted from the top level \
+and including collapsed wedges.'
+	);
+	
+	position = addOptionElement
+	(
+		position,
+' <input type="button" id="fontSizeDecrease" value="-"/>\
+<span id="fontSize"></span>\
+ <input type="button" id="fontSizeIncrease" value="+"/> Font size'
+	);
+	
+	if ( hueName )
+	{
+		hueDisplayName = attributeDisplayNames[attributeIndex(hueName)];
+		
+		position = addOptionElement
+		(
+			position + 5,
+			'<div style="float:left"> </div>' +
+			'<input type="checkbox" id="useHue" style="float:left" ' +
+			'/><div style="float:left">Color by<br/>' + hueDisplayName +
+			'</div>'
+		);
+		
+		useHueCheckBox = document.getElementById('useHue');
+		useHueCheckBox.checked = hueDefault;
+		useHueCheckBox.onclick = handleResize;
+	}
+	/*
+	position = addOptionElement
+	(
+		position + 5,
+		' <input type="checkbox" id="shorten" checked="checked" />Shorten labels</div>',
+		'Prevent labels from overlapping by shortening them'
+	);
+	
+	position = addOptionElement
+	(
+		position,
+		' <input type="checkbox" id="compress" checked="checked" />Compress',
+		'Compress wedges if needed to show the entire depth'
+	);
+	*/
+	position = addOptionElement
+	(
+		position,
+		' <input type="checkbox" id="collapse" checked="checked" />Collapse',
+		'Collapse wedges that are redundant (entirely composed of another wedge)'
+	);
+	
+	position = addOptionElement
+	(
+		position + 5,
+		' <input type="button" id="snapshot" value="Snapshot"/>',
+'Render the current view as SVG (Scalable Vector Graphics), a publication-\
+quality format that can be printed and saved (see Help for browser compatibility)'
+	);
+	
+	position = addOptionElement
+	(
+		position + 5,
+' <input type="button" id="linkButton" value="Link"/>\
+<input type="text" size="30" id="linkText"/>',
+'Show a link to this view that can be copied for bookmarking or sharing'
+	);
+	
+	position = addOptionElement
+	(
+		position + 5,
+' <input type="button" id="help" value="?"\
+onclick="window.open(\'https://sourceforge.net/p/krona/wiki/Browsing%20Krona%20charts/\', \'help\')"/>',
+'Help'
+	);
+}
+
+function arrow(angleStart, angleEnd, radiusInner)
+{
+	if ( context.globalAlpha == 0 )
+	{
+		return;
+	}
+	
+	var angleCenter = (angleStart + angleEnd) / 2;
+	var radiusArrowInner = radiusInner - gRadius / 10;//nodeRadius * gRadius;
+	var radiusArrowOuter = gRadius * 1.1;//(1 + nodeRadius);
+	var radiusArrowCenter = (radiusArrowInner + radiusArrowOuter) / 2;
+	var pointLength = (radiusArrowOuter - radiusArrowInner) / 5;
+	
+	context.fillStyle = highlightFill;
+	context.lineWidth = highlightLineWidth;
+	
+	// First, mask out the first half of the arrow.  This will prevent the tips
+	// from superimposing if the arrow goes most of the way around the circle.
+	// Masking is done by setting the clipping region to the inverse of the
+	// half-arrow, which is defined by cutting the half-arrow out of a large
+	// rectangle
+	//
+	context.beginPath();
+	context.arc(0, 0, radiusInner, angleCenter, angleEnd, false);
+	context.lineTo
+	(
+		radiusArrowInner * Math.cos(angleEnd),
+		radiusArrowInner * Math.sin(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowCenter * Math.cos(angleEnd) - pointLength * Math.sin(angleEnd),
+		radiusArrowCenter * Math.sin(angleEnd) + pointLength * Math.cos(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowOuter * Math.cos(angleEnd),
+		radiusArrowOuter * Math.sin(angleEnd)
+	);
+	context.arc(0, 0, gRadius, angleEnd, angleCenter, true);
+	context.closePath();
+	context.moveTo(-imageWidth, -imageHeight);
+	context.lineTo(imageWidth, -imageHeight);
+	context.lineTo(imageWidth, imageHeight);
+	context.lineTo(-imageWidth, imageHeight);
+	context.closePath();
+	context.save();
+	context.clip();
+	
+	// Next, draw the other half-arrow with the first half masked out
+	//
+	context.beginPath();
+	context.arc(0, 0, radiusInner, angleCenter, angleStart, true);
+	context.lineTo
+	(
+		radiusArrowInner * Math.cos(angleStart),
+		radiusArrowInner * Math.sin(angleStart)
+	);
+	context.lineTo
+	(
+		radiusArrowCenter * Math.cos(angleStart) + pointLength * Math.sin(angleStart),
+		radiusArrowCenter * Math.sin(angleStart) - pointLength * Math.cos(angleStart)
+	);
+	context.lineTo
+	(
+		radiusArrowOuter * Math.cos(angleStart),
+		radiusArrowOuter * Math.sin(angleStart)
+	);
+	context.arc(0, 0, gRadius, angleStart, angleCenter, false);
+	context.fill();
+	context.stroke();
+	
+	// Finally, remove the clipping region and draw the first half-arrow.  This
+	// half is extended slightly to fill the seam.
+	//
+	context.restore();
+	context.beginPath();
+	context.arc(0, 0, radiusInner, angleCenter - 2 / (2 * Math.PI * radiusInner), angleEnd, false);
+	context.lineTo
+	(
+		radiusArrowInner * Math.cos(angleEnd),
+		radiusArrowInner * Math.sin(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowCenter * Math.cos(angleEnd) - pointLength * Math.sin(angleEnd),
+		radiusArrowCenter * Math.sin(angleEnd) + pointLength * Math.cos(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowOuter * Math.cos(angleEnd),
+		radiusArrowOuter * Math.sin(angleEnd)
+	);
+	context.arc(0, 0, gRadius, angleEnd, angleCenter - 2 / (2 * Math.PI * gRadius), true);
+	context.fill();
+	context.stroke();
+}
+
+function attributeIndex(name)
+{
+	for ( var i = 0 ; i < attributeNames.length; i++ )
+	{
+		if ( name == attributeNames[i] )
+		{
+			return i;
+		}
+	}
+	
+	return null;
+}
+
+function checkHighlight()
+{
+	var lastHighlightedNode = highlightedNode;
+	var lastHighlightingHidden = highlightingHidden;
+	
+	highlightedNode = selectedNode;
+	resetKeyOffset();
+	
+	if ( progress == 1 )
+	{
+		selectedNode.checkHighlight();
+		if ( selectedNode.getParent() )
+		{
+			selectedNode.getParent().checkHighlightCenter();
+		}
+		
+		focusNode.checkHighlightMap();
+	}
+	
+	if ( highlightedNode != selectedNode )
+	{
+		if ( highlightedNode == focusNode )
+		{
+//			canvas.style.display='none';
+//			window.resizeBy(1,0);
+//			canvas.style.cursor='ew-resize';
+//			window.resizeBy(-1,0);
+//			canvas.style.display='inline';
+		}
+		else
+		{
+//			canvas.style.cursor='pointer';
+		}
+	}
+	else
+	{
+//		canvas.style.cursor='auto';
+	}
+	
+	if
+	(
+		(
+			true ||
+			highlightedNode != lastHighlightedNode ||
+			highlightingHidden != highlightingHiddenLast
+		) &&
+		progress == 1
+	)
+	{
+		draw(); // TODO: handle in update()
+	}
+}
+
+function checkSelectedCollapse()
+{
+	var newNode = selectedNode;
+	
+	while ( newNode.getCollapse() )
+	{
+		newNode = newNode.children[0];
+	}
+	
+	if ( newNode.children.length == 0 )
+	{
+		newNode = newNode.getParent();
+	}
+	
+	if ( newNode != selectedNode )
+	{
+		selectNode(newNode);
+	}
+}
+
+function clearSearch()
+{
+	search.value = '';
+	onSearchChange();
+}
+
+function createSVG()
+{
+	svgNS = "http://www.w3.org/2000/svg";
+	var SVG = {};
+	SVG.xlinkns = "http://www.w3.org/1999/xlink";
+	
+	var newSVG = document.createElementNS(svgNS, "svg:svg");
+	
+	newSVG.setAttribute("id", "canvas");
+	// How big is the canvas in pixels
+	newSVG.setAttribute("width", '100%');
+	newSVG.setAttribute("height", '100%');
+	// Set the coordinates used by drawings in the canvas
+//	newSVG.setAttribute("viewBox", "0 0 " + imageWidth + " " + imageHeight);
+	// Define the XLink namespace that SVG uses
+	newSVG.setAttributeNS
+	(
+		"http://www.w3.org/2000/xmlns/",
+		"xmlns:xlink",
+		SVG.xlinkns
+	);
+	
+	return newSVG;
+}
+
+function degrees(radians)
+{
+	return radians * 180 / Math.PI;
+}
+
+function draw()
+{
+	tweenFrames++;
+	//resize();
+//	context.fillRect(0, 0, imageWidth, imageHeight);
+	context.clearRect(0, 0, imageWidth, imageHeight);
+	
+	context.font = fontNormal;
+	context.textBaseline = 'middle';
+	
+	//context.strokeStyle = 'rgba(0, 0, 0, 0.3)';
+	context.translate(centerX, centerY);
+	
+	resetKeyOffset();
+	
+	head.draw(false, false); // draw pie slices
+	head.draw(true, false); // draw labels
+	
+	var pathRoot = selectedNode;
+	
+	if ( focusNode != 0 && focusNode != selectedNode )
+	{
+		context.globalAlpha = 1;
+		focusNode.drawHighlight(true);
+		pathRoot = focusNode;
+	}
+	
+	if
+	(
+		highlightedNode &&
+		highlightedNode.getDepth() >= selectedNode.getDepth() &&
+		highlightedNode != focusNode
+	)
+	{
+		if
+		(
+			progress == 1 &&
+			highlightedNode != selectedNode &&
+			(
+				highlightedNode != focusNode ||
+				focusNode.children.length > 0
+			)
+		)
+		{
+			context.globalAlpha = 1;
+			highlightedNode.drawHighlight(true);
+		}
+		
+		//pathRoot = highlightedNode;
+	}
+	else if
+	(
+		progress == 1 &&
+		highlightedNode.getDepth() < selectedNode.getDepth()
+	)
+	{
+		context.globalAlpha = 1;
+		highlightedNode.drawHighlightCenter();
+	}
+	
+	if ( quickLook && false) // TEMP
+	{
+		context.globalAlpha = 1 - progress / 2;
+		selectedNode.drawHighlight(true);
+	}
+	else if ( progress < 1 )//&& zoomOut() )
+	{
+		if ( !zoomOut)//() )
+		{
+			context.globalAlpha = selectedNode.alphaLine.current();
+			selectedNode.drawHighlight(true);
+		}
+		else if ( selectedNodeLast )
+		{
+			context.globalAlpha = 1 - 4 * Math.pow(progress - .5, 2);
+			selectedNodeLast.drawHighlight(false);
+		}
+	}
+	
+	drawDatasetName();
+	
+	//drawHistory();
+	
+	context.translate(-centerX, -centerY);
+	context.globalAlpha = 1;
+	
+	mapRadius =
+		(imageHeight / 2 - details.clientHeight - details.offsetTop) /
+		(pathRoot.getDepth() - 1) * 3 / 4 / 2;
+	
+	if ( mapRadius > maxMapRadius )
+	{
+		mapRadius = maxMapRadius;
+	}
+	
+	mapBuffer = mapRadius / 2;
+	
+	//context.font = fontNormal;
+	pathRoot.drawMap(pathRoot);
+	
+	if ( hueDisplayName && useHue() )
+	{
+		drawLegend();
+	}
+}
+
+function drawBubble(angle, radius, width, radial, flip)
+{
+	var height = fontSize * 2;
+	var x;
+	var y;
+	
+	width = width + fontSize;
+	
+	if ( radial )
+	{
+		y = -fontSize;
+		
+		if ( flip )
+		{
+			x = radius - width + fontSize / 2;
+		}
+		else
+		{
+			x = radius - fontSize / 2;
+		}
+	}
+	else
+	{
+		x = -width / 2;
+		y = -radius - fontSize;
+	}
+	
+	if ( snapshotMode )
+	{
+		drawBubbleSVG(x + centerX, y + centerY, width, height, fontSize, angle);
+	}
+	else
+	{
+		drawBubbleCanvas(x, y, width, height, fontSize, angle);
+	}
+}
+
+function drawBubbleCanvas(x, y, width, height, radius, rotation)
+{
+	context.strokeStyle = 'black';
+	context.lineWidth = highlightLineWidth;
+	context.fillStyle = 'rgba(255, 255, 255, .75)';
+	context.rotate(rotation);
+	roundedRectangle(x, y, width, fontSize * 2, fontSize);
+	context.fill();
+	context.stroke();
+	context.rotate(-rotation);
+}
+
+function drawBubbleSVG(x, y, width, height, radius, rotation)
+{
+	svg +=
+		'<rect x="' + x + '" y="' + y +
+		'" width="' + width +
+		'" height="' + height +
+		'" rx="' + radius +
+		'" ry="' + radius +
+		'" fill="rgba(255, 255, 255, .75)' +
+		'" class="highlight" ' +
+		'transform="rotate(' +
+		degrees(rotation) + ',' + centerX + ',' + centerY +
+		')"/>';
+}
+
+function drawDatasetName()
+{
+	var alpha = datasetAlpha.current();
+	
+	if ( alpha > 0 )
+	{
+		var radius = gRadius * compressedRadii[0] / -2;
+		
+		if ( alpha > 1 )
+		{
+			alpha = 1;
+		}
+		
+		context.globalAlpha = alpha;
+		
+		drawBubble(0, -radius, datasetWidths[currentDataset], false, false);
+		drawText(datasetNames[currentDataset], 0, radius, 0, 'center', true);
+	}
+}
+
+function drawHistory()
+{
+	var alpha = 1;
+	context.textAlign = 'center';
+	
+	for ( var i = 0; i < nodeHistoryPosition && alpha > 0; i++ )
+	{
+		
+		context.globalAlpha = alpha - historyAlphaDelta * tweenFactor;
+		context.fillText
+		(
+			nodeHistory[nodeHistoryPosition - i - 1].name,
+			0,
+			(i + tweenFactor) * historySpacingFactor * fontSize - 1
+		);
+		
+		if ( alpha > 0 )
+		{
+			alpha -= historyAlphaDelta;
+		}
+	}
+	
+	context.globalAlpha = 1;
+}
+
+function drawLegend()
+{
+	var left = imageWidth * .01;
+	var width = imageHeight * .0265;
+	var height = imageHeight * .15;
+	var top = imageHeight - fontSize * 3.5 - height;
+	var textLeft = left + width + fontSize / 2;
+	
+	context.fillStyle = 'black';
+	context.textAlign = 'start';
+	context.font = fontNormal;
+//	context.fillText(valueStartText, textLeft, top + height);
+//	context.fillText(valueEndText, textLeft, top);
+	context.fillText(hueDisplayName, left, imageHeight - fontSize * 1.5);
+	
+	var gradient = context.createLinearGradient(0, top + height, 0, top);
+	
+	for ( var i = 0; i < hueStopPositions.length; i++ )
+	{
+		gradient.addColorStop(hueStopPositions[i], hueStopHsl[i]);
+		
+		var textY = top + (1 - hueStopPositions[i]) * height;
+		
+		if
+		(
+			i == 0 ||
+			i == hueStopPositions.length - 1 ||
+			textY > top + fontSize && textY < top + height - fontSize
+		)
+		{
+			context.fillText(hueStopText[i], textLeft, textY);
+		}
+	}
+	
+	context.fillStyle = gradient;
+	context.fillRect(left, top, width, height);
+	context.lineWidth = thinLineWidth;
+	context.strokeRect(left, top, width, height);
+}
+
+function drawLegendSVG()
+{
+	var left = imageWidth * .01;
+	var width = imageHeight * .0265;
+	var height = imageHeight * .15;
+	var top = imageHeight - fontSize * 3.5 - height;
+	var textLeft = left + width + fontSize / 2;
+
+	var text = '';
+	
+	text += svgText(hueDisplayName, left, imageHeight - fontSize * 1.5);
+	
+	var svgtest = '<linearGradient id="gradient" x1="0%" y1="100%" x2="0%" y2="0%">';
+	
+	for ( var i = 0; i < hueStopPositions.length; i++ )
+	{
+		svgtest +=
+			'<stop offset="' + round(hueStopPositions[i] * 100) +
+			'%" style="stop-color:' + hueStopHsl[i] + '"/>';
+		
+		var textY = top + (1 - hueStopPositions[i]) * height;
+		
+		if
+		(
+			i == 0 ||
+			i == hueStopPositions.length - 1 ||
+			textY > top + fontSize && textY < top + height - fontSize
+		)
+		{
+			text += svgText(hueStopText[i], textLeft, textY);
+		}
+	}
+	
+	svgtest += '</linearGradient>';
+	//alert(svgtest);
+	svg += svgtest;
+	svg +=
+		'<rect style="fill:url(#gradient)" x="' + left + '" y="' + top +
+		'" width="' + width + '" height="' + height + '"/>';
+	
+	svg += text;
+}
+
+function drawSearchHighlights(label, bubbleX, bubbleY, rotation, center)
+{
+	var index = -1;
+	var labelLength = label.length;
+	
+	bubbleX -= fontSize / 4;
+	
+	do
+	{
+		index = label.toLowerCase().indexOf(search.value.toLowerCase(), index + 1);
+		
+		if ( index != -1 && index < labelLength )
+		{
+			var dim = context.measureText(label.substr(0, index));
+			var x = bubbleX + dim.width;
+			
+			dim = context.measureText(label.substr(index, search.value.length));
+			
+			var y = bubbleY - fontSize * 3 / 4;
+			var width = dim.width + fontSize / 2;
+			var height = fontSize * 3 / 2;
+			var radius = fontSize / 2;
+			
+			if ( snapshotMode )
+			{
+				if ( center )
+				{
+					x += centerX;
+					y += centerY;
+				}
+				
+				svg +=
+					'<rect x="' + x + '" y="' + y +
+					'" width="' + width +
+					'" height="' + height +
+					'" rx="' + radius +
+					'" ry="' + radius +
+					'" class="searchHighlight' +
+					'" transform="rotate(' +
+					degrees(rotation) + ',' + centerX + ',' + centerY +
+					')"/>';
+			}
+			else
+			{
+				context.fillStyle = 'rgb(255, 255, 100)';
+				context.rotate(rotation);
+				roundedRectangle(x, y, width, height, radius);
+				context.fill();
+				context.rotate(-rotation);
+			}
+		}
+	}
+	while ( index != -1 && index < labelLength );
+}
+
+function drawText(text, x, y, angle, anchor, bold)
+{
+	if ( snapshotMode )
+	{
+		svg +=
+			'<text x="' + (centerX + x) + '" y="' + (centerY + y) +
+			'" text-anchor="' + anchor + '" style="font-weight:' + (bold ? 'bold' : 'normal') +
+			'" transform="rotate(' + degrees(angle) + ',' + centerX + ',' + centerY + ')">' +
+			text + '</text>';
+	}
+	else
+	{
+		context.fillStyle = 'black';
+		context.textAlign = anchor;
+		context.font = bold ? fontBold : fontNormal;
+		context.rotate(angle);
+		context.fillText(text, x, y);
+		context.rotate(-angle);
+	}
+}
+
+function drawTextPolar
+(
+	text,
+	innerText,
+	angle,
+	radius,
+	radial,
+	bubble,
+	bold, 
+	searchResult,
+	searchResults
+)
+{
+	var anchor;
+	var textX;
+	var textY;
+	var spacer;
+	var totalText = text;
+	var flip;
+	
+	if ( snapshotMode )
+	{
+		spacer = '   ';
+	}
+	else
+	{
+		spacer = '   ';
+	}
+	
+	if ( radial )
+	{
+		flip = angle < 3 * Math.PI / 2;
+		
+		if ( flip )
+		{
+			angle -= Math.PI;
+			radius = -radius;
+			anchor = 'end';
+			
+			if ( innerText )
+			{
+				totalText = text + spacer + innerText;
+			}
+		}
+		else
+		{
+			anchor = 'start';
+			
+			if ( innerText )
+			{
+				totalText = innerText + spacer + text;
+			}
+		}
+		
+		textX = radius;
+		textY = 0;
+	}
+	else
+	{
+		flip = angle < Math.PI || angle > 2 * Math.PI;
+		var label;
+		
+		anchor = snapshotMode ? 'middle' : 'center';
+		
+		if ( flip )
+		{
+			angle -= Math.PI;
+			radius = -radius;
+		}
+		
+		angle += Math.PI / 2;
+		textX = 0;
+		textY = -radius;
+	}
+	
+	if ( bubble )
+	{
+		var textActual = totalText;
+		
+		if ( innerText && snapshotMode )
+		{
+			if ( flip )
+			{
+				textActual = text + '   ' + innerText;
+			}
+			else
+			{
+				textActual = innerText + '   ' + text;
+			}
+		}
+		
+		if ( searchResults )
+		{
+			textActual = textActual + searchResultString(searchResults);
+		}
+		
+		var textWidth = measureText(textActual, bold);
+		
+		var x = textX;
+		
+		if ( anchor == 'end' )
+		{
+			x -= textWidth;
+		}
+		else if ( anchor != 'start' )
+		{
+			// centered
+			x -= textWidth / 2;
+		}
+		
+		drawBubble(angle, radius, textWidth, radial, flip);
+		
+		if ( searchResult )
+		{
+			drawSearchHighlights
+			(
+				textActual,
+				x,
+				textY,
+				angle,
+				true
+			)
+		}
+	}
+	
+	if ( searchResults )
+	{
+		totalText = totalText + searchResultString(searchResults);
+	}
+	
+	drawText(totalText, textX, textY, angle, anchor, bold);
+	
+	return flip;
+}
+
+function drawTick(start, length, angle)
+{
+	if ( snapshotMode )
+	{
+		svg +=
+			'<line x1="' + (centerX + start) +
+			'" y1="' + centerY +
+			'" x2="' + (centerX + start + length) +
+			'" y2="' + centerY +
+			'" class="tick" transform="rotate(' +
+			degrees(angle) + ',' + centerX + ',' + centerY +
+			')"/>';
+	}
+	else
+	{
+		context.rotate(angle);
+		context.beginPath();
+		context.moveTo(start, 0);
+		context.lineTo(start + length, 0);
+		context.lineWidth = thinLineWidth * 2;
+		context.stroke();
+		context.rotate(-angle);
+	}
+}
+
+function drawWedge
+(
+	angleStart,
+	angleEnd,
+	radiusInner,
+	radiusOuter,
+	color,
+	patternAlpha,
+	highlight
+)
+{
+	if ( context.globalAlpha == 0 )
+	{
+		return;
+	}
+	
+	if ( snapshotMode )
+	{
+		if ( angleEnd == angleStart + Math.PI * 2 )
+		{
+			// fudge to prevent overlap, which causes arc ambiguity
+			//
+			angleEnd -= .1 / gRadius;
+		}
+		
+		var longArc = angleEnd - angleStart > Math.PI ? 1 : 0;
+		
+		var x1 = centerX + radiusInner * Math.cos(angleStart);
+		var y1 = centerY + radiusInner * Math.sin(angleStart);
+		
+		var x2 = centerX + gRadius * Math.cos(angleStart);
+		var y2 = centerY + gRadius * Math.sin(angleStart);
+		
+		var x3 = centerX + gRadius * Math.cos(angleEnd);
+		var y3 = centerY + gRadius * Math.sin(angleEnd);
+		
+		var x4 = centerX + radiusInner * Math.cos(angleEnd);
+		var y4 = centerY + radiusInner * Math.sin(angleEnd);
+		
+		var dArray =
+		[
+			" M ", x1, ",", y1,
+			" L ", x2, ",", y2,
+			" A ", gRadius, ",", gRadius, " 0 ", longArc, ",1 ", x3, ",", y3,
+			" L ", x4, ",", y4,
+			" A ", radiusInner, ",", radiusInner, " 0 ", longArc, " 0 ", x1, ",", y1,
+			" Z "
+		];
+		
+		svg +=
+			'<path class="'+ (highlight ? 'highlight' : 'wedge') + '" fill="' + color +
+			'" d="' + dArray.join('') + '"/>';
+		
+		if ( patternAlpha > 0 )
+		{
+			svg +=
+				'<path class="wedge" fill="url(#hiddenPattern)" d="' +
+				dArray.join('') + '"/>';
+		}
+	}
+	else
+	{
+		// fudge to prevent seams during animation
+		//
+		angleEnd += 1 / gRadius;
+		
+		context.fillStyle = color;
+		context.beginPath();
+		context.arc(0, 0, radiusInner, angleStart, angleEnd, false);
+		context.arc(0, 0, radiusOuter, angleEnd, angleStart, true);
+		context.closePath();
+		context.fill();
+		
+		if ( patternAlpha > 0 )
+		{
+			context.save();
+			context.clip();
+			context.globalAlpha = patternAlpha;
+			context.fillStyle = hiddenPattern;
+			context.fill();
+			context.restore();
+		}
+		
+		if ( highlight )
+		{
+			context.lineWidth = highlight ? highlightLineWidth : thinLineWidth;
+			context.strokeStyle = 'black';
+			context.stroke();
+		}
+	}
+}
+
+function expand(node)
+{
+	selectNode(node);
+	updateView();
+}
+
+function focusLost()
+{
+	mouseX = -1;
+	mouseY = -1;
+	checkHighlight();
+	document.body.style.cursor = 'auto';
+}
+
+function fontSizeDecrease()
+{
+	if ( fontSize > 1 )
+	{
+		fontSize--;
+		updateViewNeeded = true;
+	}
+}
+
+function fontSizeIncrease()
+{
+	fontSize++;
+	updateViewNeeded = true;
+}
+
+function getGetString(name, value, bool)
+{
+	return name + '=' + (bool ? value ? 'true' : 'false' : value);
+}
+
+function hideLink()
+{
+	hide(linkText);
+	show(linkButton);
+}
+
+function show(object)
+{
+	object.style.display = 'inline';
+}
+
+function hide(object)
+{
+	object.style.display = 'none';
+}
+
+function showLink()
+{
+	var urlHalves = String(document.location).split('?');
+	var newGetVariables = new Array();
+	
+	newGetVariables.push
+	(
+		getGetString('dataset', currentDataset, false),
+		getGetString('node', selectedNode.id, false),
+		getGetString('collapse', collapse, true),
+		getGetString('color', useHue(), true),
+		getGetString('depth', maxAbsoluteDepth - 1, false),
+		getGetString('font', fontSize, false),
+		getGetString('key', showKeys, true)
+	);
+	
+	hide(linkButton);
+	show(linkText);
+	linkText.value = urlHalves[0] + '?' + getVariables.concat(newGetVariables).join('&');
+	//linkText.disabled = false;
+	linkText.focus();
+	linkText.select();
+	//linkText.disabled = true;
+//	document.location = urlHalves[0] + '?' + getVariables.join('&');
+}
+
+function getPercentage(fraction)
+{
+	return round(fraction * 100);
+}
+
+function hslText(hue)
+{
+	if ( 1 || snapshotMode )
+	{
+		// Safari doesn't seem to allow hsl() in SVG
+		
+		var rgb = hslToRgb(hue, saturation, (lightnessBase + lightnessMax) / 2);
+		
+		return rgbText(rgb.r, rgb.g, rgb.b);
+	}
+	else
+	{
+		var hslArray =
+		[
+			'hsl(',
+			Math.floor(hue * 360),
+			',',
+			Math.floor(saturation * 100),
+			'%,',
+			Math.floor((lightnessBase + lightnessMax) * 50),
+			'%)'
+		];
+		
+		return hslArray.join('');
+	}
+}
+
+function hslToRgb(h, s, l)
+{
+	var m1, m2;
+	var r, g, b;
+	
+	if (s == 0)
+	{
+		r = g = b = Math.floor((l * 255));
+	}
+	else
+	{
+		if (l <= 0.5)
+		{
+			m2 = l * (s + 1);
+		}
+		else
+		{
+			m2 = l + s - l * s;
+		}
+		
+		m1 = l * 2 - m2;
+		
+		r = Math.floor(hueToRgb(m1, m2, h + 1 / 3));
+		g = Math.floor(hueToRgb(m1, m2, h));
+		b = Math.floor(hueToRgb(m1, m2, h - 1/3));
+	}
+	
+	return {r: r, g: g, b: b};
+}
+
+function hueToRgb(m1, m2, hue)
+{
+	var v;
+	if (hue < 0)
+		hue += 1;
+	else if (hue > 1)
+		hue -= 1;
+
+	if (6 * hue < 1)
+		v = m1 + (m2 - m1) * hue * 6;
+	else if (2 * hue < 1)
+		v = m2;
+	else if (3 * hue < 2)
+		v = m1 + (m2 - m1) * (2/3 - hue) * 6;
+	else
+		v = m1;
+
+	return 255 * v;
+}
+
+function interpolateHue(hueStart, hueEnd, valueStart, valueEnd)
+{
+	// since the gradient will be RGB based, we need to add stops to hit all the
+	// colors in the hue spectrum
+	
+	hueStopPositions = new Array();
+	hueStopHsl = new Array();
+	hueStopText = new Array();
+	
+	hueStopPositions.push(0);
+	hueStopHsl.push(hslText(hueStart));
+	hueStopText.push(round(valueStart));
+	
+	for
+	(
+		var i = (hueStart > hueEnd ? 5 / 6 : 1 / 6);
+		(hueStart > hueEnd ? i > 0 : i < 1);
+		i += (hueStart > hueEnd ? -1 : 1) / 6
+	)
+	{
+		if
+		(
+			hueStart > hueEnd ?
+				i > hueEnd && i < hueStart :
+				i > hueStart && i < hueEnd
+		)
+		{
+			hueStopPositions.push(lerp(i, hueStart, hueEnd, 0, 1));
+			hueStopHsl.push(hslText(i));
+			hueStopText.push(round(lerp
+			(
+				i,
+				hueStart,
+				hueEnd,
+				valueStart,
+				valueEnd
+			)));
+		}
+	}
+	
+	hueStopPositions.push(1);
+	hueStopHsl.push(hslText(hueEnd));
+	hueStopText.push(round(valueEnd));
+}
+
+function keyLineAngle(angle, keyAngle, bendRadius, keyX, keyY, pointsX, pointsY)
+{
+	if ( angle < Math.PI / 2 && keyY < bendRadius * Math.sin(angle) 
+	|| angle > Math.PI / 2 && keyY < bendRadius)
+	{
+		return Math.asin(keyY / bendRadius);
+	}
+	else
+	{
+		// find the angle of the normal to a tangent line that goes to
+		// the label
+		
+		var textDist = Math.sqrt
+		(
+			Math.pow(keyX, 2) +
+			Math.pow(keyY, 2)
+		);
+		
+		var tanAngle = Math.acos(bendRadius / textDist) + keyAngle;
+		
+		if ( angle < tanAngle || angle < Math.PI / 2 )//|| labelLeft < centerX )
+		{
+			// angle doesn't reach far enough for tangent; collapse and
+			// connect directly to label
+			
+			if ( keyY / Math.tan(angle) > 0 )
+			{
+				pointsX.push(keyY / Math.tan(angle));
+				pointsY.push(keyY);
+			}
+			else
+			{
+				pointsX.push(bendRadius * Math.cos(angle));
+				pointsY.push(bendRadius * Math.sin(angle));
+			}
+			
+			return angle;
+		}
+		else
+		{
+			return tanAngle;
+		}
+	}
+}
+
+function keyOffset()
+{
+	return imageHeight - (keys - currentKey + 1) * (keySize + keyBuffer) + keyBuffer - margin;
+}
+
+function lerp(value, fromStart, fromEnd, toStart, toEnd)
+{
+	return (value - fromStart) *
+		(toEnd - toStart) /
+		(fromEnd - fromStart) +
+		toStart;
+}
+
+function load()
+{
+	if ( context == undefined )
+	{
+		document.body.innerHTML = '\
+<br/>This browser does not support HTML5 (see \
+<a href="http://sourceforge.net/p/krona/wiki/Browser%20support/">Browser support</a>).\
+	';
+		return;
+	}
+
+	if ( typeof context.fillText != 'function' )
+	{
+		document.body.innerHTML = '\
+<br/>This browser does not support HTML5 canvas text (see \
+<a href="http://sourceforge.net/p/krona/wiki/Browser%20support/">Browser support</a>).\
+	';
+		return;
+	}
+	
+	resize();
+	
+	var xmlElements = document.getElementsByTagName('data');
+	var magnitudeName;
+	var membersAssignedName;
+	var membersSummaryName;
+	
+	var hueName;
+	var hueDefault;
+	var hueStart;
+	var hueEnd;
+	var valueStart;
+	var valueEnd;
+	
+	for ( var element = xmlElements[0].firstChild; element; element = element.nextSibling )
+	{
+		if ( element.nodeType != 1 )
+		{
+			continue;
+		}
+		
+		switch ( element.tagName.toLowerCase() )
+		{
+			case 'options':
+				for ( var i = 0; i < element.attributes.length; i++ )
+				{
+					switch ( element.attributes[i].nodeName )
+					{
+						case 'collapse':
+							collapse =
+								element.attributes[i].nodeValue == 'true';
+							break;
+						case 'key':
+							showKeys =
+								element.attributes[i].nodeValue == 'true';
+							break;
+					}
+				}
+				break;
+				
+			case 'magnitude':
+				magnitudeName = element.getAttribute('attribute');
+				break;
+			
+			case 'attributes':
+				for ( var i = 0; i < element.attributes.length; i++ )
+				{
+					attributeNames.push(element.attributes[i].nodeName);
+					attributeDisplayNames.push(element.attributes[i].nodeValue);
+				}
+				break;
+			
+			case 'members':
+				membersAssignedName = element.getAttribute('attributeAssigned');
+				membersSummaryName = element.getAttribute('attributeSummary');
+				break;
+				
+			case 'color':
+				hueName = element.getAttribute('attribute');
+				hueStart = Number(element.getAttribute('hueStart')) / 360;
+				hueEnd = Number(element.getAttribute('hueEnd')) / 360;
+				valueStart = Number(element.getAttribute('valueStart'));
+				valueEnd = Number(element.getAttribute('valueEnd'));
+				//
+				interpolateHue(hueStart, hueEnd, valueStart, valueEnd);
+				//
+				if ( element.getAttribute('default') == 'true' )
+				{
+					hueDefault = true;
+				}
+				break;
+			
+			case 'datasets':
+				datasetNames = element.getAttribute('names').split(',');
+				datasets = datasetNames.length;
+				break;
+			
+			case 'node':
+				head = loadTreeDOM
+				(
+					element,
+					magnitudeName,
+					hueName,
+					hueStart,
+					hueEnd,
+					valueStart,
+					valueEnd
+				);
+				break;
+		}
+	}
+	
+	// get GET options
+	//
+	var urlHalves = String(document.location).split('?');
+	var datasetDefault = 0;
+	var maxDepthDefault;
+	var nodeDefault = 0;
+	//
+	if ( urlHalves[1] )
+	{
+		var vars = urlHalves[1].split('&');
+		
+		for ( i = 0; i < vars.length; i++ )
+		{
+			var pair = vars[i].split('=');
+			
+			switch ( pair[0] )
+			{
+				case 'collapse':
+					collapse = pair[1] == 'true';
+					break;
+				
+				case 'color':
+					hueDefault = pair[1] == 'true';
+					break;
+				
+				case 'dataset':
+					datasetDefault = Number(pair[1]);
+					break;
+					
+				case 'depth':
+					maxDepthDefault = Number(pair[1]) + 1;
+					break;
+				
+				case 'key':
+					showKeys = pair[1] == 'true';
+					break;
+				
+				case 'font':
+					fontSize = Number(pair[1]);
+					break;
+				
+				case 'node':
+					nodeDefault = Number(pair[1]);
+					break;
+				
+				default:
+					getVariables.push(pair[0] + '=' + pair[1]);
+					break;
+			}
+		}
+	}
+	
+	// set indeces
+	//
+	for ( var i = 0; i < attributeNames.length; i++ )
+	{
+		if ( attributeNames[i] == magnitudeName )
+		{
+			magnitudeIndex = i;
+		}
+		
+		if ( attributeNames[i] == membersAssignedName )
+		{
+			membersAssignedIndex = i;
+		}
+		else if ( attributeNames[i] == membersSummaryName )
+		{
+			membersSummaryIndex = i;
+		}
+	}
+	
+	addOptionElements(hueName, hueDefault);
+	setCallBacks();
+	
+	head.sort();
+	maxAbsoluteDepth = 0;
+	selectDataset(datasetDefault);
+	
+	if ( maxDepthDefault && maxDepthDefault < head.maxDepth )
+	{
+		maxAbsoluteDepth = maxDepthDefault;
+	}
+	else
+	{
+		maxAbsoluteDepth = head.maxDepth;
+	}
+	
+	selectNode(nodes[nodeDefault]);
+	
+	setInterval(update, 20);
+	
+	window.onresize = handleResize;
+	updateMaxAbsoluteDepth();
+	updateViewNeeded = true;
+}
+
+function loadTreeDOM
+(
+	domNode,
+	magnitudeName,
+	hueName,
+	hueStart,
+	hueEnd,
+	valueStart,
+	valueEnd
+)
+{
+	var newNode = new Node();
+	
+	for ( var i = 0; i < domNode.attributes.length; i++ )
+	{
+		var attributeCurrent = domNode.attributes[i];
+		
+		if ( attributeCurrent.nodeName == 'name' )
+		{
+			newNode.name = attributeCurrent.nodeValue;
+		}
+		else if ( attributeCurrent.nodeName == 'href' )
+		{
+			newNode.href = attributeCurrent.nodeValue;
+		}
+		else if ( attributeCurrent.nodeName == 'members' )
+		{
+			var attributeValues = attributeCurrent.nodeValue.split(',');
+			
+			for ( var j = 0; j < attributeValues.length; j++ )
+			{
+				newNode.members = attributeValues[j].split(' ');
+			}
+			
+			useMembers = true;
+		}
+		else
+		{
+			var attributeValues = attributeCurrent.nodeValue.split(',');
+			
+			if
+			(
+				attributeCurrent.nodeName == magnitudeName ||
+				attributeCurrent.nodeName == hueName
+			)
+			{
+				for ( var j = 0; j < attributeValues.length; j++ )
+				{
+					attributeValues[j] = Number(attributeValues[j]);
+				}
+				
+				while ( attributeValues.length < datasets )
+				{
+					attributeValues.push(0);
+				}
+			}
+			
+			newNode.attributes[attributeIndex(attributeCurrent.nodeName)] =
+				attributeValues;
+			
+			if ( attributeCurrent.nodeName == hueName && newNode.hue == null )
+			{
+				newNode.hues = new Array();
+				
+				for ( var j = 0; j < attributeValues.length; j++ )
+				{
+					newNode.hues.push(lerp
+					(
+						attributeValues[j],
+						valueStart,
+						valueEnd,
+						hueStart,
+						hueEnd
+					));
+					
+					if ( newNode.hues[j] < hueStart == hueStart < hueEnd )
+					{
+						newNode.hues[j] = hueStart;
+					}
+					else if ( newNode.hues[j] > hueEnd == hueStart < hueEnd )
+					{
+						newNode.hues[j] = hueEnd;
+					}
+				}
+				
+				newNode.hue = new Tween(newNode.hues[0], newNode.hues[0]);
+			}
+		}
+	}
+	
+	for ( var child = domNode.firstChild; child; child = child.nextSibling )
+	{
+		if ( child.nodeType == 1 )
+		{
+			var newChild = loadTreeDOM
+			(
+				child,
+				magnitudeName,
+				hueName,
+				hueStart,
+				hueEnd,
+				valueStart,
+				valueEnd
+			);
+			newChild.parent = newNode;
+			newNode.children.push(newChild);
+		}
+	}
+	
+	return newNode;
+}
+
+function maxAbsoluteDepthDecrease()
+{
+	if ( maxAbsoluteDepth > 2 )
+	{
+		maxAbsoluteDepth--;
+		head.setMaxDepths();
+		handleResize();
+	}
+}
+
+function maxAbsoluteDepthIncrease()
+{
+	if ( maxAbsoluteDepth < head.maxDepth )
+	{
+		maxAbsoluteDepth++;
+		head.setMaxDepths();
+		handleResize();
+	}
+}
+
+function measureText(text, bold)
+{
+	context.font = bold ? fontBold : fontNormal;
+	var dim = context.measureText(text);
+	return dim.width;
+}
+
+function min(a, b)
+{
+	return a < b ? a : b;
+}
+
+function minWidth()
+{
+	// Min wedge width (at center) for displaying a node (or for displaying a
+	// label if it's at the highest level being viewed, multiplied by 2 to make
+	// further calculations simpler
+	
+	return (fontSize * 2.3);
+}
+
+function mouseMove(e)
+{
+	mouseX = e.pageX;
+	mouseY = e.pageY - headerHeight;
+	
+	if ( head && ! quickLook )
+	{
+		checkHighlight();
+	}
+}
+
+function mouseClick(e)
+{
+	if ( highlightedNode == focusNode && focusNode != selectedNode || selectedNode.hasParent(highlightedNode) )
+	{
+		if ( highlightedNode.hasChildren() )
+		{
+			expand(highlightedNode);
+		}
+	}
+	else if ( progress == 1 )//( highlightedNode != selectedNode )
+	{
+		setFocus(highlightedNode);
+//		document.body.style.cursor='ew-resize';
+		draw();
+		checkHighlight();
+		var date = new Date();
+		mouseDownTime = date.getTime();
+		mouseDown = true;
+	}
+}
+
+function mouseUp(e)
+{
+	if ( quickLook )
+	{
+		navigateBack();
+		quickLook = false;
+	}
+	
+	mouseDown = false;
+}
+
+function navigateBack()
+{
+	if ( nodeHistoryPosition > 0 )
+	{
+		nodeHistory[nodeHistoryPosition] = selectedNode;
+		nodeHistoryPosition--;
+		
+		if ( nodeHistory[nodeHistoryPosition].collapse )
+		{
+			collapseCheckBox.checked = collapse = false;
+		}
+		
+		setSelectedNode(nodeHistory[nodeHistoryPosition]);
+		updateDatasetButtons();
+		updateView();
+	}
+}
+
+function navigateUp()
+{
+	if ( selectedNode.getParent() )
+	{
+		selectNode(selectedNode.getParent());
+		updateView();
+	}
+}
+
+function navigateForward()
+{
+	if ( nodeHistoryPosition < nodeHistory.length - 1 )
+	{
+		nodeHistoryPosition++;
+		var newNode = nodeHistory[nodeHistoryPosition];
+		
+		if ( newNode.collapse )
+		{
+			collapseCheckBox.checked = collapse = false;
+		}
+		
+		if ( nodeHistoryPosition == nodeHistory.length - 1 )
+		{
+			// this will ensure the forward button is disabled
+			
+			nodeHistory.length = nodeHistoryPosition;
+		}
+		
+		setSelectedNode(newNode);
+		updateDatasetButtons();
+		updateView();
+	}
+}
+
+function nextDataset()
+{
+	var newDataset = currentDataset;
+	
+	do
+	{
+		if ( newDataset == datasets - 1 )
+		{
+			newDataset = 0;
+		}
+		else
+		{
+			newDataset++;
+		}
+	}
+	while ( datasetDropDown.options[newDataset].disabled )
+	
+	selectDataset(newDataset);
+}
+
+function onDatasetChange()
+{
+	selectDataset(datasetDropDown.selectedIndex);
+}
+
+function onKeyDown(event)
+{
+	if
+	(
+		event.keyCode == 37 &&
+		document.activeElement.id != 'search' &&
+		document.activeElement.id != 'linkText'
+	)
+	{
+		navigateBack();
+		event.preventDefault();
+	}
+	else if
+	(
+		event.keyCode == 39 &&
+		document.activeElement.id != 'search' &&
+		document.activeElement.id != 'linkText'
+	)
+	{
+		navigateForward();
+		event.preventDefault();
+	}
+	else if ( event.keyCode == 38 && datasets > 1 )
+	{
+		prevDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+	else if ( event.keyCode == 40 && datasets > 1 )
+	{
+		nextDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+	else if ( event.keyCode == 9 && datasets > 1 )
+	{
+		selectLastDataset();
+		event.preventDefault();
+	}
+	else if ( event.keyCode == 83 )
+	{
+		progress += .01;
+	}
+	else if ( event.keyCode == 66 )
+	{
+		progress -= .01;
+	}
+	else if ( event.keyCode == 70 )
+	{
+		progress = 1;
+	}
+}
+
+function onKeyUp(event)
+{
+	if ( event.keyCode == 27 && document.activeElement.id == 'search' )
+	{
+		search.value = '';
+		onSearchChange();
+	}
+}
+
+function onSearchChange()
+{
+	nSearchResults = 0;
+	head.search();
+	
+	if ( search.value == '' )
+	{
+		searchResults.innerHTML = '';
+	}
+	else
+	{
+		searchResults.innerHTML = nSearchResults + ' results';
+	}
+	
+	setFocus(selectedNode);
+	draw();
+}
+
+function prevDataset()
+{
+	var newDataset = currentDataset;
+	
+	do
+	{
+		if ( newDataset == 0 )
+		{
+			newDataset = datasets - 1;
+		}
+		else
+		{
+			newDataset--;
+		}
+	}
+	while ( datasetDropDown.options[newDataset].disabled );
+	
+	selectDataset(newDataset);
+}
+
+function resetKeyOffset()
+{
+	currentKey = 1;
+	keyMinTextLeft = centerX + gRadius + buffer - buffer / (keys + 1) / 2 + fontSize / 2;
+	keyMinAngle = 0;
+}
+
+function rgbText(r, g, b)
+{
+	var rgbArray =
+	[
+		"rgb(",
+		Math.floor(r),
+		",",
+		Math.floor(g),
+		",",
+		Math.floor(b),
+		")"
+	];
+	
+	return rgbArray.join('');
+}
+
+function round(number)
+{
+	if ( number >= 1 || number <= -1 )
+	{
+		return number.toFixed(0);
+	}
+	else
+	{
+		return number.toPrecision(1);
+	}
+}
+
+function roundedRectangle(x, y, width, height, radius)
+{
+	if ( radius * 2 > width )
+	{
+		radius = width / 2;
+	}
+	
+	if ( radius * 2 > height )
+	{
+		radius = height / 2;
+	}
+	
+	context.beginPath();
+	context.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2, false);
+	context.lineTo(x + width - radius, y);
+	context.arc(x + width - radius, y + radius, radius, Math.PI * 3 / 2, Math.PI * 2, false);
+	context.lineTo(x + width, y + height - radius);
+	context.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2, false);
+	context.lineTo(x + radius, y + height);
+	context.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI, false);
+	context.lineTo(x, y + radius);
+}
+
+function passClick(e)
+{
+	mouseClick(e);
+}
+
+function searchResultString(results)
+{
+	var searchResults = this.searchResults;
+	
+	if ( this.isSearchResult )
+	{
+		// don't count ourselves
+		searchResults--;
+	}
+	
+	return ' - ' + results + (results > 1 ? ' results' : ' result');
+}
+
+function setCallBacks()
+{
+	canvas.onselectstart = function(){return false;} // prevent unwanted highlighting
+	document.onmousemove = mouseMove;
+	window.onblur = focusLost;
+	window.onmouseout = focusLost;
+	document.onkeyup = onKeyUp;
+	document.onkeydown = onKeyDown;
+	canvas.onmousedown = mouseClick;
+	document.onmouseup = mouseUp;
+	keyControl.onclick = toggleKeys;
+	collapseCheckBox = document.getElementById('collapse');
+	collapseCheckBox.checked = collapse;
+	collapseCheckBox.onclick = handleResize;
+	maxAbsoluteDepthText = document.getElementById('maxAbsoluteDepth');
+	maxAbsoluteDepthButtonDecrease = document.getElementById('maxAbsoluteDepthDecrease');
+	maxAbsoluteDepthButtonIncrease = document.getElementById('maxAbsoluteDepthIncrease');
+	maxAbsoluteDepthButtonDecrease.onclick = maxAbsoluteDepthDecrease;
+	maxAbsoluteDepthButtonIncrease.onclick = maxAbsoluteDepthIncrease;
+	fontSizeText = document.getElementById('fontSize');
+	fontSizeButtonDecrease = document.getElementById('fontSizeDecrease');
+	fontSizeButtonIncrease = document.getElementById('fontSizeIncrease');
+	fontSizeButtonDecrease.onclick = fontSizeDecrease;
+	fontSizeButtonIncrease.onclick = fontSizeIncrease;
+	maxAbsoluteDepth = 0;
+	backButton = document.getElementById('back');
+	backButton.onclick = navigateBack;
+	forwardButton = document.getElementById('forward');
+	forwardButton.onclick = navigateForward;
+	snapshotButton = document.getElementById('snapshot');
+	snapshotButton.onclick = snapshot;
+	details = document.getElementById('details');
+	detailsName = document.getElementById('detailsName');
+	detailsExpand = document.getElementById('detailsExpand');
+	detailsInfo = document.getElementById('detailsInfo');
+	search = document.getElementById('search');
+	search.onkeyup = onSearchChange;
+	searchResults = document.getElementById('searchResults');
+	useHueDiv = document.getElementById('useHueDiv');
+	linkButton = document.getElementById('linkButton');
+	linkButton.onclick = showLink;
+	linkText = document.getElementById('linkText');
+	linkText.onblur = hideLink;
+	hide(linkText);
+	
+	image = document.getElementById('hiddenImage');
+	
+	if ( image.complete )
+	{
+		hiddenPattern = context.createPattern(image, 'repeat');
+	}
+	else
+	{
+		image.onload = function()
+		{
+			hiddenPattern = context.createPattern(image, 'repeat');
+		}
+	}
+}
+
+function selectDataset(newDataset)
+{
+	lastDataset = currentDataset;
+	currentDataset = newDataset
+	if ( datasets > 1 )
+	{
+		datasetDropDown.selectedIndex = currentDataset;
+		updateDatasetButtons();
+		datasetAlpha.start = 1.5;
+		datasetChanged = true;
+	}
+	head.setMagnitudes(0);
+	head.setDepth(1, 1);
+	head.setMaxDepths();
+	handleResize();
+}
+
+function selectLastDataset()
+{
+	selectDataset(lastDataset);
+	handleResize();
+}
+
+function selectNode(newNode)
+{
+	if ( selectedNode != newNode )
+	{
+		// truncate history at current location to create a new branch
+		//
+		nodeHistory.length = nodeHistoryPosition;
+		
+		if ( selectedNode != 0 )
+		{
+			nodeHistory.push(selectedNode);
+			nodeHistoryPosition++;
+		}
+		
+		setSelectedNode(newNode);
+		//updateView();
+	}
+	
+	updateDatasetButtons();
+}
+
+function setFocus(node)
+{
+	if ( node == focusNode )
+	{
+//		return;
+	}
+	
+	focusNode = node;
+	
+	if ( node.href )
+	{
+		detailsName.innerHTML =
+			'<a target="_blank" href="' + node.href + '">' + node.name + '</a>';
+	}
+	else
+	{
+		detailsName.innerHTML = node.name;
+	}
+	
+	var table = '<table>';
+	
+	table += '<tr><td></td></tr>';
+	
+	for ( var i = 0; i < node.attributes.length; i++ )
+	{
+		if ( node.attributes[i] != undefined )
+		{
+			var value;
+			
+			if ( node.attributes[i].length > 1 )
+			{
+				value = node.attributes[i][currentDataset];
+			}
+			else
+			{
+				value = node.attributes[i][0];
+			}
+			
+			if ( i == membersAssignedIndex )
+			{
+				value = '<a href="javascript:showAssignedMembers()" title="Show members">' + value + '</a>';
+			}
+			else if ( i == membersSummaryIndex )
+			{
+				value = '<a href="javascript:showSummaryMembers()" title="Show members">' + value + '</a>';
+			}
+			
+			table +=
+				'<tr><td><strong>' + attributeDisplayNames[i] + ':</strong></td><td>' +
+				value + '</td></tr>';
+		}
+	}
+	
+	table += '</table>';
+	detailsInfo.innerHTML = table;
+	
+	detailsExpand.disabled = !focusNode.hasChildren() || focusNode == selectedNode;
+}
+
+function setSelectedNode(newNode)
+{
+	if ( selectedNode && selectedNode.hasParent(newNode) )
+	{
+		zoomOut = true;
+	}
+	else
+	{
+		zoomOut = false;
+	}
+	
+	selectedNodeLast = selectedNode;
+	selectedNode = newNode;
+	
+	if ( focusNode != selectedNode )
+	{
+		setFocus(selectedNode);
+	}
+}
+
+function showAssignedMembers()
+{
+	if ( focusNode.members )
+	{
+		window.open
+		(
+			'data:text/plain;charset=utf-8,' +
+				encodeURIComponent(focusNode.members.join('\n')),
+			'_blank'
+		);
+	}
+}
+
+function showSummaryMembers()
+{
+	window.open
+	(
+		'data:text/plain;charset=utf-8,' +
+			encodeURIComponent(focusNode.getMembers().join('\n')),
+		'_blank'
+	);
+}
+
+function snapshot()
+{
+	svg = svgHeader();
+	
+	resetKeyOffset();
+	
+	snapshotMode = true;
+	
+	selectedNode.draw(false, true);
+	selectedNode.draw(true, true);
+	
+	if ( focusNode != 0 && focusNode != selectedNode )
+	{
+		context.globalAlpha = 1;
+		focusNode.drawHighlight(true);
+	}
+	
+	if ( hueDisplayName && useHue() )
+	{
+		drawLegendSVG();
+	}
+	
+	snapshotMode = false;
+	
+	svg += svgFooter();
+	
+	snapshotWindow = window.open
+	(
+		'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg),
+		'_blank'
+	);
+}
+
+function spacer()
+{
+	if ( snapshotMode )
+	{
+		return '   ';
+	}
+	else
+	{
+		return '   ';
+	}
+}
+
+function svgFooter()
+{
+	return '</svg>';
+}
+
+function svgHeader()
+{
+	var patternWidth = fontSize * .6;//radius / 50;
+	
+	return '\
+<?xml version="1.0" standalone="no"?>\
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" \
+	"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\
+<svg width="' + imageWidth + '" height="' + imageHeight + '" version="1.1"\
+	xmlns="http://www.w3.org/2000/svg">\
+<title>Krona (snapshot) - ' +
+(datasets > 1 ? datasetNames[currentDataset] + ' - ' : '') + selectedNode.name +
+'</title>\
+<defs>\
+	<style type="text/css">\
+	text {font-size: ' + fontSize + 'px; font-family: ' + fontFamily + '; dominant-baseline:central}\
+	path {stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	path.wedge {stroke:none}\
+	path.line {fill:none;stroke:black;}\
+	line {stroke:black;stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	line.tick {stroke-width:' + thinLineWidth * fontSize / 6 + ';}\
+	line.pattern {stroke-width:' + thinLineWidth * fontSize / 18 + ';}\
+	circle {fill:none;stroke:black;stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	rect {stroke:black;stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	.highlight {stroke:black;stroke-width:'+ highlightLineWidth * fontSize / 12 + ';}\
+	.searchHighlight {fill:rgb(255, 255, 100);stroke:none;}\
+	</style>\
+<pattern id="hiddenPattern" patternUnits="userSpaceOnUse" \
+x="0" y="0" width="' + patternWidth + '" height="' + patternWidth + '">\
+<line class="pattern" x1="0" y1="0" x2="' + patternWidth / 2 + '" y2="' + patternWidth / 2 + '"/>\
+<line class="pattern" x1="' + patternWidth / 2 + '" y1="' + patternWidth +
+'" x2="' + patternWidth + '" y2="' + patternWidth / 2 + '"/>\
+</pattern>\
+</defs>\
+';
+}
+
+function svgText(text, x, y, anchor, bold)
+{
+	if ( typeof(anchor) == 'undefined' )
+	{
+		anchor = 'start';
+	}
+	
+	return '<text x="' + x + '" y="' + y +
+		'" style="font-weight:' + (bold ? 'bold' : 'normal') +
+		'" text-anchor="' + anchor + '">' + text + '</text>';
+}
+
+function toggleKeys()
+{
+	if ( showKeys )
+	{
+		keyControl.value = '…';
+		showKeys = false;
+	}
+	else
+	{
+		keyControl.value = 'x';
+		showKeys = true;
+	}
+	
+	updateKeyControl();
+	
+	if ( progress == 1 )
+	{
+		draw();
+	}
+}
+
+function update()
+{
+	if ( ! head )
+	{
+		return;
+	}
+	
+	if ( mouseDown && focusNode != selectedNode )
+	{
+		var date = new Date();
+		
+		if ( date.getTime() - mouseDownTime > quickLookHoldLength )
+		{
+			if ( focusNode.hasChildren() )
+			{
+				expand(focusNode);
+				quickLook = true;
+			}
+		}
+	}
+	
+	if ( updateViewNeeded )
+	{
+		resize();
+		mouseX = -1;
+		mouseY = -1;
+		
+		collapse = collapseCheckBox.checked;
+		compress = true;//compressCheckBox.checked;
+		shorten = true;//shortenCheckBox.checked;
+		
+		checkSelectedCollapse();
+		updateMaxAbsoluteDepth();
+		
+		if ( focusNode.getCollapse() || focusNode.depth > maxAbsoluteDepth )
+		{
+			setFocus(selectedNode);
+		}
+		else
+		{
+			setFocus(focusNode);
+		}
+		
+		updateView();
+		
+		updateViewNeeded = false;
+	}
+	
+	var date = new Date();
+	progress = (date.getTime() - tweenStartTime) / tweenLength;
+//	progress += .01;
+	
+	if ( progress >= 1 )
+	{
+		progress = 1;
+	}
+	
+	if ( progress != progressLast )
+	{
+		tweenFactor =
+			(1 / (1 + Math.exp(-tweenCurvature * (progress - .5))) - .5) /
+			(tweenMax - .5) / 2 + .5;
+		
+		if ( progress == 1 )
+		{
+			snapshotButton.disabled = false;
+			zoomOut = false;
+			
+			//updateKeyControl();
+			
+			if ( ! quickLook )
+			{
+				//checkHighlight();
+			}
+			
+			
+			if ( fpsDisplay )
+			{
+				fpsDisplay.innerHTML = 'fps: ' + Math.round(tweenFrames * 1000 / tweenLength);
+			}
+		}
+		
+		draw();
+	}
+	
+	progressLast = progress;
+}
+
+function updateDatasetButtons()
+{
+	if ( datasets == 1 )
+	{
+		return;
+	}
+	
+	var node = selectedNode ? selectedNode : head;
+	
+	datasetButtonLast.disabled =
+		node.attributes[magnitudeIndex][lastDataset] == 0;
+	
+	datasetButtonPrev.disabled = true;
+	datasetButtonNext.disabled = true;
+	
+	for ( var i = 0; i < datasets; i++ )
+	{
+		var disable = node.attributes[magnitudeIndex][i] == 0;
+		
+		datasetDropDown.options[i].disabled = disable;
+		
+		if ( ! disable )
+		{
+			if ( i != currentDataset )
+			{
+				datasetButtonPrev.disabled = false;
+				datasetButtonNext.disabled = false;
+			}
+		}
+	}
+}
+
+function updateDatasetWidths()
+{
+	if ( datasets > 1 )
+	{
+		for ( var i = 0; i < datasets; i++ )
+		{
+			context.font = fontBold;
+			var dim = context.measureText(datasetNames[i]);
+			datasetWidths[i] = dim.width;
+		}
+	}
+}
+
+function updateKeyControl()
+{
+	if ( keys == 0 )//|| progress != 1 )
+	{
+		keyControl.style.visibility = 'hidden';
+	}
+	else
+	{
+		keyControl.style.visibility = 'visible';
+		keyControl.style.right = margin + 'px';
+		
+		if ( showKeys )
+		{
+			keyControl.style.top =
+				imageHeight -
+				(
+					keys * (keySize + keyBuffer) -
+					keyBuffer +
+					margin +
+					keyControl.clientHeight * 1.5
+				) + 'px';
+		}
+		else
+		{
+			keyControl.style.top =
+				(imageHeight - margin - keyControl.clientHeight) + 'px';
+		}
+	}
+}
+
+function updateView()
+{
+	if ( selectedNode.depth > maxAbsoluteDepth - 1 )
+	{
+		maxAbsoluteDepth = selectedNode.depth + 1;
+	}
+	
+	highlightedNode = selectedNode;
+	
+	angleFactor = 2 * Math.PI / (selectedNode.magnitude);
+	
+	maxPossibleDepth = Math.floor(gRadius / (fontSize * minRingWidthFactor));
+	
+	if ( maxPossibleDepth < 4 )
+	{
+		maxPossibleDepth = 4;
+	}
+	
+	var minRadiusInner = fontSize * 8 / gRadius;
+	var minRadiusFirst = fontSize * 6 / gRadius;
+	var minRadiusOuter = fontSize * 5 / gRadius;
+	
+	if ( .25 < minRadiusInner )
+	{
+		minRadiusInner = .25;
+	}
+	
+	if ( .15 < minRadiusFirst )
+	{
+		minRadiusFirst = .15;
+	}
+	
+	if ( .15 < minRadiusOuter )
+	{
+		minRadiusOuter = .15;
+	}
+	
+	// visibility of nodes depends on the depth they are displayed at,
+	// so we need to set the max depth assuming they can all be displayed
+	// and iterate it down based on the deepest child node we can display
+	//
+	var maxDepth;
+	var newMaxDepth = selectedNode.getMaxDepth() - selectedNode.getDepth() + 1;
+	//
+	do
+	{
+		maxDepth = newMaxDepth;
+		
+		if ( ! compress && maxDepth > maxPossibleDepth )
+		{
+			maxDepth = maxPossibleDepth;
+		}
+		
+		if ( compress )
+		{
+			compressedRadii = new Array(maxDepth);
+			
+			compressedRadii[0] = minRadiusInner;
+			
+			var offset = 0;
+			
+			while
+			(
+				lerp
+				(
+					Math.atan(offset + 2),
+					Math.atan(offset + 1),
+					Math.atan(maxDepth + offset - 1),
+					minRadiusInner,
+					1 - minRadiusOuter
+				) - minRadiusInner > minRadiusFirst &&
+				offset < 10
+			)
+			{
+				offset++;
+			}
+			
+			offset--;
+			
+			for ( var i = 1; i < maxDepth; i++ )
+			{
+				compressedRadii[i] = lerp
+				(
+					Math.atan(i + offset),
+					Math.atan(offset),
+					Math.atan(maxDepth + offset - 1),
+					minRadiusInner,
+					1 - minRadiusOuter
+				)
+			}
+		}
+		else
+		{
+			nodeRadius = 1 / maxDepth;
+		}
+		
+		newMaxDepth = selectedNode.maxVisibleDepth(maxDepth);
+		
+		if ( compress )
+		{
+			if ( newMaxDepth <= maxPossibleDepth )
+			{
+//				compress
+			}
+		}
+		else
+		{
+			if ( newMaxDepth > maxPossibleDepth )
+			{
+				newMaxDepth = maxPossibleDepth;
+			}
+		}
+	}
+	while ( newMaxDepth < maxDepth );
+	
+	maxDisplayDepth = maxDepth;
+	
+	lightnessFactor = (lightnessMax - lightnessBase) / (maxDepth > 8 ? 8 : maxDepth);
+	keys = 0;
+	
+	nLabelOffsets = new Array(maxDisplayDepth - 1);
+	labelOffsets = new Array(maxDisplayDepth - 1);
+	labelLastNodes = new Array(maxDisplayDepth - 1);
+	labelFirstNodes = new Array(maxDisplayDepth - 1);
+	
+	for ( var i = 0; i < maxDisplayDepth - 1; i++ )
+	{
+		if ( compress )
+		{
+			if ( i == maxDisplayDepth - 1 )
+			{
+				nLabelOffsets[i] = 0;
+			}
+			else
+			{
+				var width =
+					(compressedRadii[i + 1] - compressedRadii[i]) *
+					gRadius;
+				
+				nLabelOffsets[i] = Math.floor(width / fontSize / 1.2);
+				
+				if ( nLabelOffsets[i] > 2 )
+				{
+					nLabelOffsets[i] = min
+					(
+						Math.floor(width / fontSize / 1.75),
+						5
+					);
+				}
+			}
+		}
+		else
+		{
+			nLabelOffsets[i] = Math.max
+			(
+				Math.floor(Math.sqrt((nodeRadius * gRadius / fontSize)) * 1.5),
+				3
+			);
+		}
+		
+		labelOffsets[i] = Math.floor((nLabelOffsets[i] - 1) / 2);
+		labelLastNodes[i] = new Array(nLabelOffsets[i] + 1);
+		labelFirstNodes[i] = new Array(nLabelOffsets[i] + 1);
+		
+		for ( var j = 0; j <= nLabelOffsets[i]; j++ )
+		{
+			// these arrays will allow nodes with neighboring labels to link to
+			// each other to determine max label length
+			
+			labelLastNodes[i][j] = 0;
+			labelFirstNodes[i][j] = 0;
+		}
+	}
+	
+	fontSizeText.innerHTML = fontSize;
+	fontNormal = fontSize + 'px ' + fontFamily;
+	context.font = fontNormal;
+	fontBold = 'bold ' + fontSize + 'px ' + fontFamily;
+	tickLength = fontSize * .7;
+	
+	head.setTargets(0);
+	
+	keySize = ((imageHeight - margin * 3) * 1 / 2) / keys * 3 / 4;
+	
+	if ( keySize > fontSize * maxKeySizeFactor )
+	{
+		keySize = fontSize * maxKeySizeFactor;
+	}
+	
+	keyBuffer = keySize / 3;
+	
+	fontSizeLast = fontSize;
+	
+	if ( datasetChanged )
+	{
+		datasetChanged = false;
+	}
+	else
+	{
+		datasetAlpha.start = 0;
+	}
+	
+	var date = new Date();
+	tweenStartTime = date.getTime();
+	progress = 0;
+	tweenFrames = 0;
+	
+	updateKeyControl();
+	updateDatasetWidths();
+	
+	document.title = 'Krona - ' + selectedNode.name;
+	updateNavigationButtons();
+	snapshotButton.disabled = true;
+	
+	maxAbsoluteDepthText.innerHTML = maxAbsoluteDepth - 1;
+	
+	maxAbsoluteDepthButtonDecrease.disabled = (maxAbsoluteDepth == 2);
+	maxAbsoluteDepthButtonIncrease.disabled = (maxAbsoluteDepth == head.maxDepth);
+	
+	if ( collapse != collapseLast && search.value != '' )
+	{
+		onSearchChange();
+		collapseLast = collapse;
+	}
+}
+
+function updateMaxAbsoluteDepth()
+{
+	while ( selectedNode.depth > maxAbsoluteDepth - 1 )
+	{
+		selectedNode = selectedNode.getParent();
+	}
+}
+
+function updateNavigationButtons()
+{
+	backButton.disabled = (nodeHistoryPosition == 0);
+//	upButton.disabled = (selectedNode.getParent() == 0);
+	forwardButton.disabled = (nodeHistoryPosition == nodeHistory.length);
+}
+
+function useHue()
+{
+	return useHueCheckBox && useHueCheckBox.checked;
+}
+/*
+function zoomOut()
+{
+	return (
+		selectedNodeLast != 0 &&
+		selectedNodeLast.getDepth() < selectedNode.getDepth());
+}
+*/
\ No newline at end of file
diff --git a/KronaTools/src/krona-2.0.js b/KronaTools/src/krona-2.0.js
new file mode 100644
index 0000000..a146fc6
--- /dev/null
+++ b/KronaTools/src/krona-2.0.js
@@ -0,0 +1,6597 @@
+{//-----------------------------------------------------------------------------
+// 
+// PURPOSE
+// 
+// Krona is a flexible tool for exploring the relative proportions of
+// hierarchical data, such as metagenomic classifications, using a
+// radial, space-filling display. It is implemented using HTML5 and
+// JavaScript, allowing charts to be explored locally or served over the
+// Internet, requiring only a current version of any major web
+// browser. Krona charts can be created using an Excel template or from
+// common bioinformatic formats using the provided conversion scripts.
+// 
+// 
+// COPYRIGHT LICENSE
+// 
+// Copyright (c) 2011, Battelle National Biodefense Institute (BNBI);
+// all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+// Adam Phillippy
+// 
+// This Software was prepared for the Department of Homeland Security
+// (DHS) by the Battelle National Biodefense Institute, LLC (BNBI) as
+// part of contract HSHQDC-07-C-00020 to manage and operate the National
+// Biodefense Analysis and Countermeasures Center (NBACC), a Federally
+// Funded Research and Development Center.
+// 
+// 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 Battelle National Biodefense Institute 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
+// HOLDER 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.
+// 
+// 
+// TRADEMARK LICENSE
+// 
+// KRONA(TM) is a trademark of the Department of Homeland Security, and use
+// of the trademark is subject to the following conditions:
+// 
+// * Distribution of the unchanged, official code/software using the
+//   KRONA(TM) mark is hereby permitted by the Department of Homeland
+//   Security, provided that the software is distributed without charge
+//   and modification.
+// 
+// * Distribution of altered source code/software using the KRONA(TM) mark
+//   is not permitted unless written permission has been granted by the
+//   Department of Homeland Security.
+// 
+// 
+// FOR MORE INFORMATION VISIT
+// 
+// https://github.com/marbl/Krona/wiki/
+// 
+//-----------------------------------------------------------------------------
+}
+
+
+var canvas;
+var context;
+var svg; // for snapshot mode
+var collapse = true;
+var collapseCheckBox;
+var collapseLast;
+var compress;
+var compressCheckBox;
+var maxAbsoluteDepthText;
+var maxAbsoluteDepthButtonDecrease;
+var maxAbsoluteDepthButtonIncrease;
+var fontSize = 11;
+var fontSizeText;
+var fontSizeButtonDecrease;
+var fontSizeButtonIncrease;
+var fontSizeLast;
+var radiusButtonDecrease;
+var radiusButtonIncrease;
+var shorten;
+var shortenCheckBox;
+var maxAbsoluteDepth;
+var backButton;
+var upButton;
+var forwardButton;
+var snapshotButton;
+var snapshotMode = false;
+var details;
+var detailsName;
+var search;
+var searchResults;
+var nSearchResults;
+var useHueCheckBox;
+var useHueDiv;
+var datasetDropDown;
+var datasetButtonLast;
+var datasetButtonPrev;
+var datasetButtonNext;
+var keyControl;
+var showKeys = true;
+var linkButton;
+var linkText;
+var frame;
+
+// Node references. Note that the meanings of 'selected' and 'focused' are
+// swapped in the docs.
+//
+var head; // the root of the entire tree
+var selectedNode = 0; // the root of the current view
+var focusNode = 0; // a node chosen for more info (single-click)
+var highlightedNode = 0; // mouse hover node
+var highlightingHidden = false;
+var nodes = new Array();
+var currentNodeID = 0; // to iterate while loading
+
+var nodeHistory = new Array();
+var nodeHistoryPosition = 0;
+
+var dataEnabled = false; // true when supplemental files are present
+
+// store non-Krona GET variables so they can be passed on to links
+//
+var getVariables = new Array();
+
+// selectedNodeLast is separate from the history, since we need to check
+// properties of the last node viewed when browsing through the history
+//
+var selectedNodeLast = 0;
+var zoomOut = false;
+
+// temporary zoom-in while holding the mouse button on a wedge
+//
+var quickLook = false; // true when in quick look state
+var mouseDown = false;
+var mouseDownTime; // to detect mouse button hold
+var quickLookHoldLength = 200;
+
+var imageWidth;
+var imageHeight;
+var centerX;
+var centerY;
+var gRadius;
+var updateViewNeeded = false;
+
+// Determines the angle that the pie chart starts at.  90 degrees makes the
+// center label consistent with the children.
+//
+var rotationOffset = Math.PI / 2;
+
+var buffer;
+var bufferFactor = .1;
+
+// The maps are the small pie charts showing the current slice being viewed.
+//
+var mapBuffer = 10;
+var mapRadius = 0;
+var maxMapRadius = 25;
+var mapWidth = 150;
+var maxLabelOverhang = Math.PI * 4.18;
+
+// Keys are the labeled boxes for slices in the highest level that are too thin
+// to label.
+//
+var maxKeySizeFactor = 2; // will be multiplied by font size
+var keySize;
+var keys;
+var keyBuffer = 10;
+var currentKey;
+var keyMinTextLeft;
+var keyMinAngle;
+
+var minRingWidthFactor = 5; // will be multiplied by font size
+var maxPossibleDepth; // the theoretical max that can be displayed
+var maxDisplayDepth; // the actual depth that will be displayed
+var headerHeight = 0;//document.getElementById('options').clientHeight;
+var historySpacingFactor = 1.6; // will be multiplied by font size
+var historyAlphaDelta = .25;
+
+// appearance
+//
+var lineOpacity = 0.3;
+var saturation = 0.5;
+var lightnessBase = 0.6;
+var lightnessMax = .8;
+var thinLineWidth = .3;
+var highlightLineWidth = 1.5;
+var labelBoxBuffer = 6;
+var labelBoxRounding = 15;
+var labelWidthFudge = 1.05; // The width of unshortened labels are set slightly
+							// longer than the name width so the animation
+							// finishes faster.
+var fontNormal;
+var fontBold;
+var fontFamily = 'sans-serif';
+//var fontFaceBold = 'bold Arial';
+var nodeRadius;
+var angleFactor;
+var tickLength;
+var compressedRadii;
+
+// colors
+//
+var highlightFill = 'rgba(255, 255, 255, .3)';
+var colorUnclassified = 'rgb(220,220,220)';
+
+// label staggering
+//
+var labelOffsets; // will store the current offset at each depth
+//
+// This will store pointers to the last node that had a label in each offset (or "track") of a
+// each depth.  These will be used to shorten neighboring labels that would overlap.
+// The [nLabelNodes] index will store the last node with a radial label.
+// labelFirstNodes is the same, but to check for going all the way around and
+// overlapping the first labels.
+//
+var labelLastNodes;
+var labelFirstNodes;
+//
+var nLabelOffsets = 3; // the number of offsets to use
+
+var mouseX = -1;
+var mouseY = -1;
+var mouseXRel = -1;
+var mouseYRel = -1;
+
+// tweening
+//
+var progress = 0; // for tweening; goes from 0 to 1.
+var progressLast = 0;
+var tweenFactor = 0; // progress converted by a curve for a smoother effect.
+var tweenLength = 850; // in ms
+var tweenCurvature = 13;
+//
+// tweenMax is used to scale the sigmoid function so its range is [0,1] for the
+// domain [0,1]
+//
+var tweenMax = 1 / (1 + Math.exp(-tweenCurvature / 2));
+//
+var tweenStartTime;
+
+// for framerate debug
+//
+var tweenFrames = 0;
+var fpsDisplay = document.getElementById('frameRate');
+
+// Arrays to translate xml attribute names into displayable attribute names
+//
+var attributes = new Array();
+//
+var magnitudeIndex; // the index of attribute arrays used for magnitude
+var membersAssignedIndex;
+var membersSummaryIndex;
+
+// For defining gradients
+//
+var hueDisplayName;
+var hueStopPositions;
+var hueStopHues;
+var hueStopText;
+
+// multiple datasets
+//
+var currentDataset = 0;
+var lastDataset = 0;
+var datasets = 1;
+var datasetNames;
+var datasetSelectSize = 30;
+var datasetAlpha = new Tween(0, 0);
+var datasetWidths = new Array();
+var datasetChanged;
+var datasetSelectWidth = 50;
+
+window.onload = load;
+
+var image;
+var hiddenPattern;
+var loadingImage;
+var logoImage;
+
+function backingScale()
+{
+	if ('devicePixelRatio' in window)
+	{
+		if (window.devicePixelRatio > 1)
+		{
+			return window.devicePixelRatio;
+		}
+	}
+	
+	return 1;
+}
+
+function resize()
+{
+	imageWidth = window.innerWidth;
+	imageHeight = window.innerHeight;
+	
+	if ( ! snapshotMode )
+	{
+		context.canvas.width = imageWidth * backingScale();
+		context.canvas.height = imageHeight * backingScale();
+		context.canvas.style.width = imageWidth + "px"
+		context.canvas.style.height = imageHeight + "px"
+		context.scale(backingScale(), backingScale());
+	}
+	
+	if ( datasetDropDown )
+	{
+		var ratio = 
+			(datasetDropDown.offsetTop + datasetDropDown.clientHeight) * 2 /
+			imageHeight;
+		
+		if ( ratio > 1 )
+		{
+			ratio = 1;
+		}
+		
+		ratio = Math.sqrt(ratio);
+		
+		datasetSelectWidth = 
+			(datasetDropDown.offsetLeft + datasetDropDown.clientWidth) * ratio;
+	}
+	var leftMargin = datasets > 1 ? datasetSelectWidth + 30 : 0;
+	var minDimension = imageWidth - mapWidth - leftMargin > imageHeight ?
+		imageHeight :
+		imageWidth - mapWidth - leftMargin;
+	
+	maxMapRadius = minDimension * .03;
+	buffer = minDimension * bufferFactor;
+	margin = minDimension * .015;
+	centerX = (imageWidth - mapWidth - leftMargin) / 2 + leftMargin;
+	centerY = imageHeight / 2;
+	gRadius = minDimension / 2 - buffer;
+	//context.font = '11px sans-serif';
+}
+
+function handleResize()
+{
+	updateViewNeeded = true;
+}
+
+function Attribute()
+{
+}
+
+function Tween(start, end)
+{
+	this.start = start;
+	this.end = end;
+	this.current = this.start;
+	
+	this.current = function()
+	{
+		if ( progress == 1 || this.start == this.end )
+		{
+			return this.end;
+		}
+		else
+		{
+			return this.start + tweenFactor * (this.end - this.start);
+		}
+	};
+	
+	this.setTarget = function(target)
+	{
+		this.start = this.current();
+		this.end = target;
+	}
+}
+
+function Node()
+{
+	this.id = currentNodeID;
+	currentNodeID++;
+	nodes[this.id] = this;
+	
+	this.angleStart = new Tween(Math.PI, 0);
+	this.angleEnd = new Tween(Math.PI, 0);
+	this.radiusInner = new Tween(1, 1);
+	this.labelRadius = new Tween(1, 1);
+	this.labelWidth = new Tween(0, 0);
+	this.scale = new Tween(1, 1); // TEMP
+	this.radiusOuter = new Tween(1, 1);
+	
+	this.r = new Tween(255, 255);
+	this.g = new Tween(255, 255);
+	this.b = new Tween(255, 255);
+	
+	this.alphaLabel = new Tween(0, 1);
+	this.alphaLine = new Tween(0, 1);
+	this.alphaArc = new Tween(0, 0);
+	this.alphaWedge = new Tween(0, 1);
+	this.alphaOther = new Tween(0, 1);
+	this.alphaPattern = new Tween(0, 0);
+	this.children = Array();
+	this.parent = 0;
+	
+	this.attributes = new Array(attributes.length);
+	
+	this.addChild = function(child)
+	{
+		this.children.push(child);
+	};
+	
+	this.addLabelNode = function(depth, labelOffset)
+	{
+		if ( labelHeadNodes[depth][labelOffset] == 0 )
+		{
+			// this will become the head node for this list
+			
+			labelHeadNodes[depth][labelOffset] = this;
+			this.labelPrev = this;
+		}
+		
+		var head = labelHeadNodes[depth][labelOffset];
+		
+		this.labelNext = head;
+		this.labelPrev = head.labelPrev;
+		head.labelPrev.labelNext = this;
+		head.labelPrev = this;
+	}
+	
+	this.canDisplayDepth = function()
+	{
+		// whether this node is at a depth that can be displayed, according
+		// to the max absolute depth
+		
+		return this.depth <= maxAbsoluteDepth;
+	}
+	
+	this.canDisplayHistory = function()
+	{
+		var radiusInner;
+		
+		if ( compress )
+		{
+			radiusInner = compressedRadii[0];
+		}
+		else
+		{
+			radiusInner = nodeRadius;
+		}
+		
+		return (
+			-this.labelRadius.end * gRadius +
+			historySpacingFactor * fontSize / 2 <
+			radiusInner * gRadius
+			);
+	}
+	
+	this.canDisplayLabelCurrent = function()
+	{
+		return (
+			(this.angleEnd.current() - this.angleStart.current()) *
+			(this.radiusInner.current() * gRadius + gRadius) >=
+			minWidth());
+	}
+	
+	this.checkHighlight = function()
+	{
+		if ( this.children.length == 0 && this == focusNode )
+		{
+			//return false;
+		}
+		
+		if ( this.hide )
+		{
+			return false;
+		}
+		
+		if ( this.radiusInner.end == 1 )
+		{
+			// compressed to the outside; don't check
+			
+			return false;
+		}
+		
+		var highlighted = false;
+		
+		var angleStartCurrent = this.angleStart.current() + rotationOffset;
+		var angleEndCurrent = this.angleEnd.current() + rotationOffset;
+		var radiusInner = this.radiusInner.current() * gRadius;
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			highlighted = this.children[i].checkHighlight();
+			
+			if ( highlighted )
+			{
+				return true;
+			}
+		}
+		
+		if ( this.radial )
+		{
+			var angleText = (angleStartCurrent + angleEndCurrent) / 2;
+			var radiusText = (gRadius + radiusInner) / 2;
+			
+			context.rotate(angleText);
+			context.beginPath();
+			context.moveTo(radiusText, -fontSize);
+			context.lineTo(radiusText, fontSize);
+			context.lineTo(radiusText + centerX, fontSize);
+			context.lineTo(radiusText + centerX, -fontSize);
+			context.closePath();
+			context.rotate(-angleText);
+			
+			if ( context.isPointInPath(mouseXRel, mouseYRel) )
+			{
+				var label = String(this.getPercentage()) + '%' + '   ' + this.name;
+				
+				if ( this.searchResultChildren() )
+			    {
+					label += searchResultString(this.searchResultChildren());
+				}
+				
+				if
+				(
+					Math.sqrt((mouseXRel) * (mouseXRel) + (mouseYRel) * (mouseYRel)) / backingScale() <
+					radiusText + measureText(label)
+				)
+				{
+					highlighted = true;
+				}
+			}
+		}
+		else
+		{
+		    for ( var i = 0; i < this.hiddenLabels.length; i++ )
+		    {
+		        var hiddenLabel = this.hiddenLabels[i];
+		        
+				context.rotate(hiddenLabel.angle);
+				context.beginPath();
+				context.moveTo(gRadius, -fontSize);
+				context.lineTo(gRadius, fontSize);
+				context.lineTo(gRadius + centerX, fontSize);
+				context.lineTo(gRadius + centerX, -fontSize);
+				context.closePath();
+				context.rotate(-hiddenLabel.angle);
+				
+				if ( context.isPointInPath(mouseXRel, mouseYRel) )
+				{
+					var label = String(hiddenLabel.value) + ' more';
+					
+					if ( hiddenLabel.search )
+				    {
+						label += searchResultString(hiddenLabel.search);
+					}
+					
+					if
+					(
+						Math.sqrt((mouseXRel) * (mouseXRel) + (mouseYRel) * (mouseYRel)) / backingScale() <
+						gRadius + fontSize + measureText(label)
+					)
+					{
+						highlighted = true;
+						break;
+					}
+				}
+			}
+		}
+		
+		if ( ! highlighted && this != selectedNode && ! this.getCollapse() )
+		{
+			context.beginPath();
+			context.arc(0, 0, radiusInner, angleStartCurrent, angleEndCurrent, false);
+			context.arc(0, 0, gRadius, angleEndCurrent, angleStartCurrent, true);
+			context.closePath();
+			
+			if ( context.isPointInPath(mouseXRel, mouseYRel) )
+			{
+				highlighted = true;
+			}
+			
+			if
+			(
+				! highlighted &&
+				(angleEndCurrent - angleStartCurrent) *
+				(radiusInner + gRadius) <
+				minWidth() &&
+				this.getDepth() == selectedNode.getDepth() + 1
+			)
+			{
+				if ( showKeys && this.checkHighlightKey() )
+				{
+					highlighted = true;
+				}
+			}
+		}
+		
+		if ( highlighted )
+		{
+			if ( this != highlightedNode )
+			{
+			//	document.body.style.cursor='pointer';
+			}
+			
+			highlightedNode = this;
+		}
+		
+		return highlighted;
+	}
+	
+	this.checkHighlightCenter = function()
+	{
+		if ( ! this.canDisplayHistory() )
+		{
+			return;
+		}
+		
+		var cx = centerX;
+		var cy = centerY - this.labelRadius.end * gRadius;
+		//var dim = context.measureText(this.name);
+		
+		var width = this.nameWidth;
+		
+		if ( this.searchResultChildren() )
+		{
+			var results = searchResultString(this.searchResultChildren());
+			var dim = context.measureText(results);
+			width += dim.width;
+		}
+		
+		if
+		(
+			mouseX > cx - width / 2 &&
+			mouseX < cx + width / 2 &&
+			mouseY > cy - historySpacingFactor * fontSize / 2 &&
+			mouseY < cy + historySpacingFactor * fontSize / 2
+		)
+		{
+			highlightedNode = this;
+			return;
+		}
+		
+		if ( this.getParent() )
+		{
+			this.getParent().checkHighlightCenter();
+		}
+	}
+	
+	this.checkHighlightKey = function()
+	{
+		var offset = keyOffset();
+		
+		var xMin = imageWidth - keySize - margin - this.keyNameWidth - keyBuffer;
+		var xMax = imageWidth - margin;
+		var yMin = offset;
+		var yMax = offset + keySize;
+		
+		currentKey++;
+		
+		return (
+			mouseX > xMin &&
+			mouseX < xMax &&
+			mouseY > yMin &&
+			mouseY < yMax);
+	}
+	
+	this.checkHighlightMap = function()
+	{
+		if ( this.parent )
+		{
+			this.parent.checkHighlightMap();
+		}
+		
+		if ( this.getCollapse() || this == focusNode )
+		{
+			return;
+		}
+		
+		var box = this.getMapPosition();
+		
+		if
+		(
+			mouseX > box.x - mapRadius &&
+			mouseX < box.x + mapRadius &&
+			mouseY > box.y - mapRadius &&
+			mouseY < box.y + mapRadius
+		)
+		{
+			highlightedNode = this;
+		}
+	}
+	
+/*	this.collapse = function()
+	{
+		for (var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i] = this.children[i].collapse();
+		}
+		
+		if
+		(
+			this.children.length == 1 &&
+			this.children[0].magnitude == this.magnitude
+		)
+		{
+			this.children[0].parent = this.parent;
+			this.children[0].getDepth() = this.parent.getDepth() + 1;
+			return this.children[0];
+		}
+		else
+		{
+			return this;
+		}
+	}
+*/	
+	this.draw = function(labelMode, selected, searchHighlighted)
+	{
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+//		var hidden = false;
+		
+		if ( selectedNode == this )
+		{
+			selected = true;
+		}
+		
+		var angleStartCurrent = this.angleStart.current() + rotationOffset;
+		var angleEndCurrent = this.angleEnd.current() + rotationOffset;
+		var radiusInner = this.radiusInner.current() * gRadius;
+		var canDisplayLabelCurrent = this.canDisplayLabelCurrent();
+		var hiddenSearchResults = false;
+		
+/*		if ( ! this.hide )
+		{
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				if ( this.children[i].hide && this.children[i].searchResults )
+				{
+					hiddenSearchResults = true;
+				}
+			}
+		}
+*/		
+		var drawChildren =
+			( ! this.hide || ! this.hidePrev && progress < 1 ) &&
+			( ! this.hideAlone || ! this.hideAlonePrev && progress < 1 );
+		
+//		if ( this.alphaWedge.current() > 0 || this.alphaLabel.current() > 0 )
+		{
+			var lastChildAngleEnd;
+			
+			if ( this.hasChildren() )//canDisplayChildren )
+			{
+				lastChildAngleEnd =
+					this.children[this.children.length - 1].angleEnd.current()
+					+ rotationOffset;
+			}
+			
+			if ( labelMode )
+			{
+				var drawRadial =
+				!(
+					this.parent &&
+					this.parent != selectedNode &&
+					angleEndCurrent == this.parent.angleEnd.current() + rotationOffset
+				);
+				
+				if ( angleStartCurrent != angleEndCurrent )
+				{
+					this.drawLines(angleStartCurrent, angleEndCurrent, radiusInner, drawRadial, selected);
+				}
+				
+				var alphaOtherCurrent = this.alphaOther.current();
+				var childRadiusInner;
+				
+				if ( this == selectedNode || alphaOtherCurrent )
+				{
+					childRadiusInner =
+						this.children[this.children.length - 1].radiusInner.current() * gRadius;
+				}
+				
+				if ( this == selectedNode )
+				{
+					this.drawReferenceRings(childRadiusInner);
+				}
+				
+				if
+				(
+					selected &&
+					! searchHighlighted &&
+					this != selectedNode &&
+					(
+						this.isSearchResult ||
+						this.hideAlone && this.searchResultChildren() ||
+						false
+//						this.hide &&
+//						this.containsSearchResult
+					)
+				)
+				{
+					context.globalAlpha = this.alphaWedge.current();
+					
+					drawWedge
+					(
+						angleStartCurrent,
+						angleEndCurrent,
+						radiusInner,
+						gRadius,
+						highlightFill,
+						0,
+						true
+					);
+					
+					if
+					(
+						this.keyed &&
+						! showKeys &&
+						this.searchResults &&
+						! searchHighlighted &&
+						this != highlightedNode &&
+						this != focusNode
+					)
+					{
+						var angle = (angleEndCurrent + angleStartCurrent) / 2;
+						this.drawLabel(angle, true, false, true, true);
+					}
+					
+					//this.drawHighlight(false);
+					searchHighlighted = true;
+				}
+				
+				if
+				(
+					this == selectedNode ||
+//					true
+					//(canDisplayLabelCurrent) &&
+					this != highlightedNode &&
+					this != focusNode
+				)
+				{
+					if ( this.radial != this.radialPrev && this.alphaLabel.end == 1 )
+					{
+						context.globalAlpha = tweenFactor;
+					}
+					else
+					{
+						context.globalAlpha = this.alphaLabel.current();
+					}
+					
+					this.drawLabel
+					(
+						(angleStartCurrent + angleEndCurrent) / 2,
+						this.hideAlone && this.searchResultChildren() ||
+						(this.isSearchResult || hiddenSearchResults) && selected,
+						this == selectedNode && ! this.radial,
+						selected,
+						this.radial
+					);
+					
+					if ( this.radial != this.radialPrev && this.alphaLabel.start == 1 && progress < 1 )
+					{
+						context.globalAlpha = 1 - tweenFactor;
+						
+						this.drawLabel
+						(
+							(angleStartCurrent + angleEndCurrent) / 2,
+							(this.isSearchResult || hiddenSearchResults) && selected,
+							this == selectedNodeLast && ! this.radialPrev,
+							selected,
+							this.radialPrev
+						);
+					}
+				}
+				
+				if
+				(
+					alphaOtherCurrent &&
+					lastChildAngleEnd != null
+				)
+				{
+					if
+					(
+						(angleEndCurrent - lastChildAngleEnd) *
+						(childRadiusInner + gRadius) >=
+						minWidth()
+					)
+					{
+						//context.font = fontNormal;
+						context.globalAlpha = this.alphaOther.current();
+						
+						drawTextPolar
+						(
+							this.getUnclassifiedText(),
+							this.getUnclassifiedPercentage(),
+							(lastChildAngleEnd + angleEndCurrent) / 2,
+							(childRadiusInner + gRadius) / 2,
+							true,
+							false,
+							false,
+							0,
+							0
+						);
+					}
+				}
+				
+				if ( this == selectedNode && this.keyUnclassified && showKeys )
+				{
+					this.drawKey
+					(
+						(lastChildAngleEnd + angleEndCurrent) / 2,
+						false,
+						false
+					);
+				}
+			}
+			else
+			{
+				var alphaWedgeCurrent = this.alphaWedge.current();
+				
+				if ( alphaWedgeCurrent || this.alphaOther.current() )
+				{
+					var currentR = this.r.current();
+					var currentG = this.g.current();
+					var currentB = this.b.current();
+						
+					var fill = rgbText(currentR, currentG, currentB);
+					
+					var radiusOuter;
+					var lastChildAngle;
+					var truncateWedge =
+					(
+						this.hasChildren() &&
+						! this.keyed &&
+						(compress || depth < maxDisplayDepth) &&
+						drawChildren
+					);
+					
+					if ( truncateWedge )
+					{
+						radiusOuter = this.children[0].radiusInner.current() * gRadius;
+					}
+					else
+					{
+						radiusOuter = gRadius;
+					}
+					/*
+					if ( this.hasChildren() )
+					{
+						radiusOuter = this.children[0].getUncollapsed().radiusInner.current() * gRadius + 1;
+					}
+					else
+					{ // TEMP
+						radiusOuter = radiusInner + nodeRadius * gRadius;
+						
+						if ( radiusOuter > gRadius )
+						{
+							radiusOuter = gRadius;
+						}
+					}
+					*/
+					context.globalAlpha = alphaWedgeCurrent;
+					
+					if ( radiusInner != radiusOuter )
+					{
+						drawWedge
+						(
+							angleStartCurrent,
+							angleEndCurrent,
+							radiusInner,
+							radiusOuter,//this.radiusOuter.current() * gRadius,
+							//'rgba(0, 200, 0, .1)',
+							fill,
+							this.alphaPattern.current()
+						);
+						
+						if ( truncateWedge )
+						{
+							// fill in the extra space if the sum of our childrens'
+							// magnitudes is less than ours
+							
+							if ( lastChildAngleEnd < angleEndCurrent )//&& false) // TEMP
+							{
+								if ( radiusOuter > 1 )
+								{
+									// overlap slightly to hide the seam
+									
+	//								radiusOuter -= 1;
+								}
+								
+								if ( alphaWedgeCurrent < 1 )
+								{
+									context.globalAlpha = this.alphaOther.current();
+									drawWedge
+									(
+										lastChildAngleEnd,
+										angleEndCurrent,
+										radiusOuter,
+										gRadius,
+										colorUnclassified,
+										0
+									);
+									context.globalAlpha = alphaWedgeCurrent;
+								}
+								
+								drawWedge
+								(
+									lastChildAngleEnd,
+									angleEndCurrent,
+									radiusOuter,
+									gRadius,//this.radiusOuter.current() * gRadius,
+									//'rgba(200, 0, 0, .1)',
+									fill,
+									this.alphaPattern.current()
+								);
+							}
+						}
+						
+						if ( radiusOuter < gRadius )
+						{
+							// patch up the seam
+							//
+							context.beginPath();
+							context.arc(0, 0, radiusOuter, angleStartCurrent/*lastChildAngleEnd*/, angleEndCurrent, false);
+							context.strokeStyle = fill;
+							context.lineWidth = 1;
+							context.stroke();
+						}
+					}
+					
+					if ( this.keyed && selected && showKeys )//&& progress == 1 )
+					{
+						this.drawKey
+						(
+							(angleStartCurrent + angleEndCurrent) / 2,
+							(
+								this == highlightedNode ||
+								this == focusNode ||
+								this.searchResults
+							),
+							this == highlightedNode || this == focusNode
+						);
+					}
+				}
+			}
+		}
+		
+		this.hiddenLabels = Array();
+		
+		if ( drawChildren )
+		{
+			// draw children
+			//
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				if ( this.drawHiddenChildren(i, selected, labelMode, searchHighlighted) )
+				{
+					i = this.children[i].hiddenEnd;
+				}
+				else
+				{
+					this.children[i].draw(labelMode, selected, searchHighlighted);
+				}
+			}
+		}
+	};
+	
+	this.drawHiddenChildren = function
+	(
+		firstHiddenChild,
+		selected,
+		labelMode,
+		searchHighlighted
+	)
+	{
+		var firstChild = this.children[firstHiddenChild];
+		
+		if ( firstChild.hiddenEnd == null || firstChild.radiusInner.current() == 1 )
+		{
+			return false;
+		}
+		
+		for ( var i = firstHiddenChild; i < firstChild.hiddenEnd; i++ )
+		{
+			if ( ! this.children[i].hide || ! this.children[i].hidePrev && progress < 1 )
+			{
+				return false;
+			}
+		}
+		
+		var angleStart = firstChild.angleStart.current() + rotationOffset;
+		var lastChild = this.children[firstChild.hiddenEnd];
+		var angleEnd = lastChild.angleEnd.current() + rotationOffset;
+		var radiusInner = gRadius * firstChild.radiusInner.current();
+		var hiddenChildren = firstChild.hiddenEnd - firstHiddenChild + 1;
+		
+		if ( labelMode )
+		{
+			var hiddenSearchResults = 0;
+			
+			for ( var i = firstHiddenChild; i <= firstChild.hiddenEnd; i++ )
+			{
+				hiddenSearchResults += this.children[i].searchResults;
+				
+				if ( this.children[i].magnitude == 0 )
+				{
+					hiddenChildren--;
+				}
+			}
+			
+			if
+			(
+				selected &&
+				(angleEnd - angleStart) * 
+				(gRadius + gRadius) >=
+				minWidth() ||
+				this == highlightedNode &&
+				hiddenChildren ||
+				hiddenSearchResults
+			)
+			{
+				context.globalAlpha = this.alphaWedge.current();
+				
+				this.drawHiddenLabel
+				(
+					angleStart,
+					angleEnd,
+					hiddenChildren,
+					hiddenSearchResults
+				);
+			}
+		}
+		
+		var drawWedges = true;
+		
+		for ( var i = firstHiddenChild; i <= firstChild.hiddenEnd; i++ )
+		{
+			// all hidden children must be completely hidden to draw together
+			
+			if ( this.children[i].alphaPattern.current() != this.children[i].alphaWedge.current() )
+			{
+				drawWedges = false;
+				break;
+			}
+		}
+		
+		if ( labelMode )
+		{
+			if ( drawWedges )
+			{
+				var drawRadial = (angleEnd < this.angleEnd.current() + rotationOffset);
+				this.drawLines(angleStart, angleEnd, radiusInner, drawRadial);
+			}
+			
+			if ( hiddenSearchResults && ! searchHighlighted )
+			{
+				drawWedge
+				(
+					angleStart,
+					angleEnd,
+					radiusInner,
+					gRadius,//this.radiusOuter.current() * gRadius,
+					highlightFill,
+					0,
+					true
+				);
+			}
+		}
+		else if ( drawWedges )
+		{
+			context.globalAlpha = this.alphaWedge.current();
+			
+			var fill = rgbText
+			(
+				firstChild.r.current(),
+				firstChild.g.current(),
+				firstChild.b.current()
+			);
+			
+			drawWedge
+			(
+				angleStart,
+				angleEnd,
+				radiusInner,
+				gRadius,//this.radiusOuter.current() * gRadius,
+				fill,
+				context.globalAlpha,
+				false
+			);
+		}
+		
+		return drawWedges;
+	}
+	
+	this.drawHiddenLabel = function(angleStart, angleEnd, value, hiddenSearchResults)
+	{
+		var textAngle = (angleStart + angleEnd) / 2;
+		var labelRadius = gRadius + fontSize;//(radiusInner + radius) / 2;
+		
+		var hiddenLabel = Array();
+		
+		hiddenLabel.value = value;
+		hiddenLabel.angle = textAngle;
+		hiddenLabel.search = hiddenSearchResults;
+		
+		this.hiddenLabels.push(hiddenLabel);
+		
+		drawTick(gRadius - fontSize * .75, fontSize * 1.5, textAngle);
+		drawTextPolar
+		(
+			value.toString() + ' more',
+			0, // inner text
+			textAngle,
+			labelRadius,
+			true, // radial
+			hiddenSearchResults, // bubble
+			this == highlightedNode || this == focusNode, // bold
+			false,
+			hiddenSearchResults
+		);
+	}
+	
+	this.drawHighlight = function(bold)
+	{
+		var angleStartCurrent = this.angleStart.current() + rotationOffset;
+		var angleEndCurrent = this.angleEnd.current() + rotationOffset;
+		var radiusInner = this.radiusInner.current() * gRadius;
+		
+		//this.setHighlightStyle();
+		
+		if ( this == focusNode && this == highlightedNode && this.hasChildren() )
+		{
+//			context.fillStyle = "rgba(255, 255, 255, .3)";
+			arrow
+			(
+				angleStartCurrent,
+				angleEndCurrent,
+				radiusInner
+			);
+		}
+		else
+		{
+			drawWedge
+			(
+				angleStartCurrent,
+				angleEndCurrent,
+				radiusInner,
+				gRadius,
+				highlightFill,
+				0,
+				true
+			);
+		}
+		
+		// check if hidden children should be highlighted
+		//
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			if
+			(
+				this.children[i].getDepth() - selectedNode.getDepth() + 1 <=
+				maxDisplayDepth &&
+				this.children[i].hiddenEnd != null
+			)
+			{
+				var firstChild = this.children[i];
+				var lastChild = this.children[firstChild.hiddenEnd];
+				var hiddenAngleStart = firstChild.angleStart.current() + rotationOffset;
+				var hiddenAngleEnd = lastChild.angleEnd.current() + rotationOffset;
+				var hiddenRadiusInner = gRadius * firstChild.radiusInner.current();
+				
+				drawWedge
+				(
+					hiddenAngleStart,
+					hiddenAngleEnd,
+					hiddenRadiusInner,
+					gRadius,
+					'rgba(255, 255, 255, .3)',
+					0,
+					true
+				);
+				
+				if ( false && ! this.searchResults )
+				{
+					this.drawHiddenLabel
+					(
+						hiddenAngleStart,
+						hiddenAngleEnd,
+						firstChild.hiddenEnd - i + 1
+					);
+				}
+				
+				i = firstChild.hiddenEnd;
+			}
+		}
+		
+//			context.strokeStyle = 'black';
+		context.fillStyle = 'black';
+		
+		var highlight = ! ( progress < 1 && zoomOut && this == selectedNodeLast );
+		
+		var angle = (angleEndCurrent + angleStartCurrent) / 2;
+		
+		if ( ! (this.keyed && showKeys) )
+		{
+			this.drawLabel(angle, true, bold, true, this.radial);
+		}
+	}
+	
+	this.drawHighlightCenter = function()
+	{
+		if ( ! this.canDisplayHistory() )
+		{
+			return;
+		}
+		
+		context.lineWidth = highlightLineWidth;
+		context.strokeStyle = 'black';
+		context.fillStyle = "rgba(255, 255, 255, .6)";
+		
+		context.fillStyle = 'black';
+		this.drawLabel(3 * Math.PI / 2, true, true, false);
+		context.font = fontNormal;
+	}
+	
+	this.drawKey = function(angle, highlight, bold)
+	{
+		var offset = keyOffset();
+		var color;
+		var colorText = this.magnitude == 0 ? 'gray' : 'black';
+		var patternAlpha = this.alphaPattern.end;
+		var boxLeft = imageWidth - keySize - margin;
+		var textY = offset + keySize / 2;
+		
+		var label;
+		var keyNameWidth;
+		
+		if ( this == selectedNode )
+		{
+			color = colorUnclassified;
+			label =
+				this.getUnclassifiedText() +
+				'   ' +
+				this.getUnclassifiedPercentage();
+			keyNameWidth = measureText(label, false);
+		}
+		else
+		{
+			label = this.keyLabel;
+			color = rgbText(this.r.end, this.g.end, this.b.end);
+			
+			if ( highlight )
+			{
+				if ( this.searchResultChildren() )
+				{
+					label = label + searchResultString(this.searchResultChildren());
+				}
+				
+				keyNameWidth = measureText(label, bold);
+			}
+			else
+			{
+				keyNameWidth = this.keyNameWidth;
+			}
+		}
+		
+		var textLeft = boxLeft - keyBuffer - keyNameWidth - fontSize / 2;
+		var labelLeft = textLeft;
+		
+		if ( labelLeft > keyMinTextLeft - fontSize / 2 )
+		{
+			keyMinTextLeft -= fontSize / 2;
+			
+			if ( keyMinTextLeft < centerX - gRadius + fontSize / 2 )
+			{
+				keyMinTextLeft = centerX - gRadius + fontSize / 2;
+			}
+			
+			labelLeft = keyMinTextLeft;
+		}
+		
+		var lineX = new Array();
+		var lineY = new Array();
+		
+		var bendRadius;
+		var keyAngle = Math.atan((textY - centerY) / (labelLeft - centerX));
+		var arcAngle;
+		
+		if ( keyAngle < 0 )
+		{
+			keyAngle += Math.PI;
+		}
+		
+		if ( keyMinAngle == 0 || angle < keyMinAngle )
+		{
+			keyMinAngle = angle;
+		}
+		
+		if ( angle > Math.PI && keyMinAngle > Math.PI )
+		{
+			// allow lines to come underneath the chart
+			
+			angle -= Math.PI * 2;
+		}
+		
+		lineX.push(Math.cos(angle) * gRadius);
+		lineY.push(Math.sin(angle) * gRadius);
+		
+		if ( angle < keyAngle && textY > centerY + Math.sin(angle) * (gRadius + buffer * (currentKey - 1) / (keys + 1) / 2 + buffer / 2) )
+		{
+			bendRadius = gRadius + buffer - buffer * currentKey / (keys + 1) / 2;
+		}
+		else
+		{
+			bendRadius = gRadius + buffer * currentKey / (keys + 1) / 2 + buffer / 2;
+		}
+		
+		var outside =
+			Math.sqrt
+			(
+				Math.pow(labelLeft - centerX, 2) +
+				Math.pow(textY - centerY, 2)
+			) > bendRadius;
+		
+		if ( ! outside )
+		{
+			arcAngle = Math.asin((textY - centerY) / bendRadius);
+			
+			keyMinTextLeft = min(keyMinTextLeft, centerX + bendRadius * Math.cos(arcAngle) - fontSize / 2);
+			
+			if ( labelLeft < textLeft && textLeft > centerX + bendRadius * Math.cos(arcAngle) )
+			{
+				lineX.push(textLeft - centerX);
+				lineY.push(textY - centerY);
+			}
+		}
+		else
+		{
+			keyMinTextLeft = min(keyMinTextLeft, labelLeft - fontSize / 2);
+			
+			if ( angle < keyAngle )
+			{
+				// flip everything over y = x
+				//
+				arcAngle = Math.PI / 2 - keyLineAngle
+				(
+					Math.PI / 2 - angle,
+					Math.PI / 2 - keyAngle,
+					bendRadius,
+					textY - centerY,
+					labelLeft - centerX,
+					lineY,
+					lineX
+				);
+				
+			}
+			else
+			{
+				arcAngle = keyLineAngle
+				(
+					angle,
+					keyAngle,
+					bendRadius,
+					labelLeft - centerX,
+					textY - centerY,
+					lineX,
+					lineY
+				);
+			}
+		}
+		
+		if ( labelLeft > centerX + bendRadius * Math.cos(arcAngle) ||
+		textY > centerY + bendRadius * Math.sin(arcAngle) + .01)
+//		if ( outside ||  )
+		{
+			lineX.push(labelLeft - centerX);
+			lineY.push(textY - centerY);
+			
+			if ( textLeft != labelLeft )
+			{
+				lineX.push(textLeft - centerX);
+				lineY.push(textY - centerY);
+			}
+		}
+		
+		context.globalAlpha = this.alphaWedge.current();
+		
+		if ( snapshotMode )
+		{
+			var labelSVG;
+			
+			if ( this == selectedNode )
+			{
+				labelSVG =
+					this.getUnclassifiedText() +
+					spacer() +
+					this.getUnclassifiedPercentage();
+			}
+			else
+			{
+				labelSVG = this.name + spacer() + this.getPercentage() + '%';
+			}
+			
+			svg +=
+				'<rect fill="' + color + '" ' +
+				'x="' + boxLeft + '" y="' + offset +
+				'" width="' + keySize + '" height="' + keySize + '"/>';
+			
+			if ( patternAlpha )
+			{
+				svg +=
+					'<rect fill="url(#hiddenPattern)" style="stroke:none" ' +
+					'x="' + boxLeft + '" y="' + offset +
+					'" width="' + keySize + '" height="' + keySize + '"/>';
+			}
+			
+			svg +=
+				'<path class="line' +
+				(highlight ? ' highlight' : '') +
+				'" d="M ' + (lineX[0] + centerX) + ',' +
+				(lineY[0] + centerY);
+			
+			if ( angle != arcAngle )
+			{
+				svg +=
+					' L ' + (centerX + bendRadius * Math.cos(angle)) + ',' +
+					(centerY + bendRadius * Math.sin(angle)) +
+					' A ' + bendRadius + ',' + bendRadius + ' 0 ' +
+					'0,' + (angle > arcAngle ? '0' : '1') + ' ' +
+					(centerX + bendRadius * Math.cos(arcAngle)) + ',' +
+					(centerY + bendRadius * Math.sin(arcAngle));
+			}
+			
+			for ( var i = 1; i < lineX.length; i++ )
+			{
+				svg +=
+					' L ' + (centerX + lineX[i]) + ',' +
+					(centerY + lineY[i]);
+			}
+			
+			svg += '"/>';
+			
+			if ( highlight )
+			{
+				if ( this.searchResultChildren() )
+				{
+					labelSVG = labelSVG + searchResultString(this.searchResultChildren());
+				}
+				
+				drawBubbleSVG
+				(
+					boxLeft - keyBuffer - keyNameWidth - fontSize / 2,
+					textY - fontSize,
+					keyNameWidth + fontSize,
+					fontSize * 2,
+					fontSize,
+					0
+				);
+				
+				if ( this.isSearchResult )
+				{
+					drawSearchHighlights
+					(
+						label,
+						boxLeft - keyBuffer - keyNameWidth,
+						textY,
+						0
+					)
+				}
+			}
+			
+			svg += svgText(labelSVG, boxLeft - keyBuffer, textY, 'end', bold, colorText);
+		}
+		else
+		{
+			context.fillStyle = color;
+			context.translate(-centerX, -centerY);
+			context.strokeStyle = 'black';
+				context.globalAlpha = 1;//this.alphaWedge.current();
+			
+			context.fillRect(boxLeft, offset, keySize, keySize);
+			
+			if ( patternAlpha )
+			{
+				context.globalAlpha = patternAlpha;
+				context.fillStyle = hiddenPattern;
+				
+				// make clipping box for Firefox performance
+				context.beginPath();
+				context.moveTo(boxLeft, offset);
+				context.lineTo(boxLeft + keySize, offset);
+				context.lineTo(boxLeft + keySize, offset + keySize);
+				context.lineTo(boxLeft, offset + keySize);
+				context.closePath();
+				context.save();
+				context.clip();
+				
+				context.fillRect(boxLeft, offset, keySize, keySize);
+				context.fillRect(boxLeft, offset, keySize, keySize);
+				
+				context.restore(); // remove clipping region
+			}
+			
+			if ( highlight )
+			{
+				this.setHighlightStyle();
+				context.fillRect(boxLeft, offset, keySize, keySize);
+			}
+			else
+			{
+				context.lineWidth = thinLineWidth;
+			}
+			
+			context.strokeRect(boxLeft, offset, keySize, keySize);
+			
+			if ( lineX.length )
+			{
+				context.beginPath();
+				context.moveTo(lineX[0] + centerX, lineY[0] + centerY);
+				
+				context.arc(centerX, centerY, bendRadius, angle, arcAngle, angle > arcAngle);
+				
+				for ( var i = 1; i < lineX.length; i++ )
+				{
+					context.lineTo(lineX[i] + centerX, lineY[i] + centerY);
+				}
+				
+				context.globalAlpha = this == selectedNode ?
+					this.children[0].alphaWedge.current() :
+					this.alphaWedge.current();
+				context.lineWidth = highlight ? highlightLineWidth : thinLineWidth;
+				context.stroke();
+				context.globalAlpha = 1;
+			}
+			
+			if ( highlight )
+			{
+				drawBubbleCanvas
+				(
+					boxLeft - keyBuffer - keyNameWidth - fontSize / 2,
+					textY - fontSize,
+					keyNameWidth + fontSize,
+					fontSize * 2,
+					fontSize,
+					0
+				);
+				
+				if ( this.isSearchResult )
+				{
+					drawSearchHighlights
+					(
+						label,
+						boxLeft - keyBuffer - keyNameWidth,
+						textY,
+						0
+					)
+				}
+			}
+			
+			drawText(label, boxLeft - keyBuffer, offset + keySize / 2, 0, 'end', bold, colorText);
+			
+			context.translate(centerX, centerY);
+		}
+		
+		currentKey++;
+	}
+	
+	this.drawLabel = function(angle, bubble, bold, selected, radial)
+	{
+		if ( context.globalAlpha == 0 )
+		{
+			return;
+		}
+		
+		var innerText;
+		var label;
+		var radius;
+		
+		if ( radial )
+		{
+			radius = (this.radiusInner.current() + 1) * gRadius / 2;
+		}
+		else
+		{
+			radius = this.labelRadius.current() * gRadius;
+		}
+		
+		if ( radial && (selected || bubble ) )
+		{
+			var percentage = this.getPercentage();
+			innerText = percentage + '%';
+		}
+		
+		if
+		(
+			! radial &&
+			this != selectedNode &&
+			! bubble &&
+			( !zoomOut || this != selectedNodeLast)
+		)
+		{
+			label = this.shortenLabel();
+		}
+		else
+		{
+			label = this.name;
+		}
+		
+		var flipped = drawTextPolar
+		(
+			label,
+			innerText,
+			angle,
+			radius,
+			radial,
+			bubble,
+			bold,
+//			this.isSearchResult && this.shouldAddSearchResultsString() && (!selected || this == selectedNode || highlight),
+			this.isSearchResult && (!selected || this == selectedNode || bubble),
+			(this.hideAlone || !selected || this == selectedNode ) ? this.searchResultChildren() : 0
+		);
+		
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		
+		if
+		(
+			! radial &&
+			! bubble &&
+			this != selectedNode &&
+			this.angleEnd.end != this.angleStart.end &&
+			nLabelOffsets[depth - 2] > 2 &&
+			this.labelWidth.current() > (this.angleEnd.end - this.angleStart.end) * Math.abs(radius) &&
+			! ( zoomOut && this == selectedNodeLast ) &&
+			this.labelRadius.end > 0
+		)
+		{
+			// name extends beyond wedge; draw tick mark towards the central
+			// radius for easier identification
+			
+			var radiusCenter = compress ?
+				(compressedRadii[depth - 1] + compressedRadii[depth - 2]) / 2 :
+				(depth - .5) * nodeRadius;
+			
+			if ( this.labelRadius.end > radiusCenter )
+			{
+				if ( flipped )
+				{
+					drawTick(radius - tickLength * 1.4 , tickLength, angle);
+				}
+				else
+				{
+					drawTick(radius - tickLength * 1.7, tickLength, angle);
+				}
+			}
+			else
+			{
+				if ( flipped )
+				{
+					drawTick(radius + tickLength * .7, tickLength, angle);
+				}
+				else
+				{
+					drawTick(radius + tickLength * .4, tickLength, angle);
+				}
+			}
+		}
+	}
+	
+	this.drawLines = function(angleStart, angleEnd, radiusInner, drawRadial, selected)
+	{
+		if ( snapshotMode )
+		{
+			if ( this != selectedNode)
+			{
+				if ( angleEnd == angleStart + Math.PI * 2 )
+				{
+					// fudge to prevent overlap, which causes arc ambiguity
+					//
+					angleEnd -= .1 / gRadius;
+				}
+				
+				var longArc = angleEnd - angleStart > Math.PI ? 1 : 0;
+				
+				var x1 = centerX + radiusInner * Math.cos(angleStart);
+				var y1 = centerY + radiusInner * Math.sin(angleStart);
+				
+				var x2 = centerX + gRadius * Math.cos(angleStart);
+				var y2 = centerY + gRadius * Math.sin(angleStart);
+				
+				var x3 = centerX + gRadius * Math.cos(angleEnd);
+				var y3 = centerY + gRadius * Math.sin(angleEnd);
+				
+				var x4 = centerX + radiusInner * Math.cos(angleEnd);
+				var y4 = centerY + radiusInner * Math.sin(angleEnd);
+				
+				if ( this.alphaArc.end )
+				{
+					var dArray =
+					[
+						" M ", x4, ",", y4,
+						" A ", radiusInner, ",", radiusInner, " 0 ", longArc,
+							" 0 ", x1, ",", y1
+					];
+					
+					svg += '<path class="line" d="' + dArray.join('') + '"/>';
+				}
+				
+				if ( drawRadial && this.alphaLine.end )
+				{
+					svg += '<line x1="' + x3 + '" y1="' + y3 + '" x2="' + x4 + '" y2="' + y4 + '"/>';
+				}
+			}
+		}
+		else
+		{
+			context.lineWidth = thinLineWidth;
+			context.strokeStyle = 'black';
+			context.beginPath();
+			context.arc(0, 0, radiusInner, angleStart, angleEnd, false);
+			context.globalAlpha = this.alphaArc.current();
+			context.stroke();
+			
+			if ( drawRadial )
+			{
+				var x1 = radiusInner * Math.cos(angleEnd);
+				var y1 = radiusInner * Math.sin(angleEnd);
+				var x2 = gRadius * Math.cos(angleEnd);
+				var y2 = gRadius * Math.sin(angleEnd);
+				
+				context.beginPath();
+				context.moveTo(x1, y1);
+				context.lineTo(x2, y2);
+				
+//				if ( this.getCollapse() )//( selected && this != selectedNode )
+				{
+					context.globalAlpha = this.alphaLine.current();
+				}
+				
+				context.stroke();
+			}
+		}
+	}
+	
+	this.drawMap = function(child)
+	{
+		if ( this.parent )
+		{
+			this.parent.drawMap(child);
+		}
+		
+		if ( this.getCollapse() && this != child || this == focusNode )
+		{
+			return;
+		}
+		
+		var angleStart =
+			(child.baseMagnitude - this.baseMagnitude) / this.magnitude * Math.PI * 2 +
+			rotationOffset;
+		var angleEnd =
+			(child.baseMagnitude - this.baseMagnitude + child.magnitude) /
+			this.magnitude * Math.PI * 2 +
+			rotationOffset;
+		
+		var box = this.getMapPosition();
+		
+		context.save();
+		context.fillStyle = 'black';
+		context.textAlign = 'end';
+		context.textBaseline = 'middle';
+		
+		var textX = box.x - mapRadius - mapBuffer;
+		var percentage = getPercentage(child.magnitude / this.magnitude);
+		
+		var highlight = this == selectedNode || this == highlightedNode;
+		
+		if ( highlight )
+		{
+			context.font = fontBold;
+		}
+		else
+		{
+			context.font = fontNormal;
+		}
+		
+		context.fillText(percentage + '% of', textX, box.y - mapRadius / 3);
+		context.fillText(this.name, textX, box.y + mapRadius / 3);
+		
+		if ( highlight )
+		{
+			context.font = fontNormal;
+		}
+		
+		if ( this == highlightedNode && this != selectedNode )
+		{
+			context.fillStyle = 'rgb(245, 245, 245)';
+//			context.fillStyle = 'rgb(200, 200, 200)';
+		}
+		else
+		{
+			context.fillStyle = 'rgb(255, 255, 255)';
+		}
+		
+		context.beginPath();
+		context.arc(box.x, box.y, mapRadius, 0, Math.PI * 2, true);
+		context.closePath();
+		context.fill();
+		
+		if ( this == selectedNode )
+		{
+			context.lineWidth = 1;
+			context.fillStyle = 'rgb(100, 100, 100)';
+		}
+		else
+		{
+			if ( this == highlightedNode )
+			{
+				context.lineWidth = .2;
+				context.fillStyle = 'rgb(190, 190, 190)';
+			}
+			else
+			{
+				context.lineWidth = .2;
+				context.fillStyle = 'rgb(200, 200, 200)';
+			}
+		}
+		
+		var maxDepth = this.getMaxDepth();
+		
+		if ( ! compress && maxDepth > maxPossibleDepth + this.getDepth() - 1 )
+		{
+			maxDepth = maxPossibleDepth + this.getDepth() - 1;
+		}
+		
+		if ( this.getDepth() < selectedNode.getDepth() )
+		{
+			if ( child.getDepth() - 1 >= maxDepth )
+			{
+				maxDepth = child.getDepth();
+			}
+		}
+		
+		var radiusInner;
+		
+		if ( compress )
+		{
+			radiusInner = 0;
+//				Math.atan(child.getDepth() - this.getDepth()) /
+//				Math.PI * 2 * .9;
+		}
+		else
+		{
+			radiusInner =
+				(child.getDepth() - this.getDepth()) /
+				(maxDepth - this.getDepth() + 1);
+		}
+		
+		context.stroke();
+		context.beginPath();
+		
+		if ( radiusInner == 0 )
+		{
+			context.moveTo(box.x, box.y);
+		}
+		else
+		{
+			context.arc(box.x, box.y, mapRadius * radiusInner, angleEnd, angleStart, true);
+		}
+		
+		context.arc(box.x, box.y, mapRadius, angleStart, angleEnd, false);
+		context.closePath();
+		context.fill();
+		
+		if ( this == highlightedNode && this != selectedNode )
+		{
+			context.lineWidth = 1;
+			context.stroke();
+		}
+		
+		context.restore();
+	}
+	
+	this.drawReferenceRings = function(childRadiusInner)
+	{
+		if ( snapshotMode )
+		{
+			svg +=
+				'<circle cx="' + centerX + '" cy="' + centerY +
+				'" r="' + childRadiusInner + '"/>';
+			svg +=
+				'<circle cx="' + centerX + '" cy="' + centerY +
+				'" r="' + gRadius + '"/>';
+		}
+		else
+		{
+			context.globalAlpha = 1 - this.alphaLine.current();//this.getUncollapsed().alphaLine.current();
+			context.beginPath();
+			context.arc(0, 0, childRadiusInner, 0, Math.PI * 2, false);
+			context.stroke();
+			context.beginPath();
+			context.arc(0, 0, gRadius, 0, Math.PI * 2, false);
+			context.stroke();
+		}
+	}
+	
+	this.getCollapse = function()
+	{
+		return (
+			collapse &&
+			this.collapse &&
+			this.depth != maxAbsoluteDepth
+			);
+	}
+	
+	this.getDepth = function()
+	{
+		if ( collapse )
+		{
+			return this.depthCollapsed;
+		}
+		else
+		{
+			return this.depth;
+		}
+	}
+	
+	this.getMagnitude = function()
+	{
+		return this.attributes[magnitudeIndex][currentDataset];
+	}
+	
+	this.getMapPosition = function()
+	{
+		return {
+			x : (details.offsetLeft + details.clientWidth - mapRadius),
+			y : ((focusNode.getDepth() - this.getDepth()) *
+				(mapBuffer + mapRadius * 2) - mapRadius) +
+				details.clientHeight + details.offsetTop
+		};
+	}
+	
+	this.getMaxDepth = function(limit)
+	{
+		var max;
+		
+		if ( collapse )
+		{
+			return this.maxDepthCollapsed;
+		}
+		else
+		{
+			if ( this.maxDepth > maxAbsoluteDepth )
+			{
+				return maxAbsoluteDepth;
+			}
+			else
+			{
+				return this.maxDepth;
+			}
+		}
+	}
+	
+	this.getData = function(index, summary)
+	{
+		var files = new Array();
+		
+		if
+		(
+			this.attributes[index] != null &&
+			this.attributes[index][currentDataset] != null &&
+			this.attributes[index][currentDataset] != ''
+		)
+		{
+			files.push
+			(
+				document.location +
+				'.files/' +
+				this.attributes[index][currentDataset]
+			);
+		}
+		
+		if ( summary )
+		{
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				files = files.concat(this.children[i].getData(index, true));
+			}
+		}
+		
+		return files;
+	}
+	
+	this.getList = function(index, summary)
+	{
+		var list;
+		
+		if
+		(
+			this.attributes[index] != null &&
+			this.attributes[index][currentDataset] != null
+		)
+		{
+			list = this.attributes[index][currentDataset];
+		}
+		else
+		{
+			list = new Array();
+		}
+		
+		if ( summary )
+		{
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				list = list.concat(this.children[i].getList(index, true));
+			}
+		}
+		
+		return list;
+	}
+	
+	this.getParent = function()
+	{
+		// returns parent, accounting for collapsing or 0 if doesn't exist
+		
+		var parent = this.parent;
+		
+		while ( parent != 0 && parent.getCollapse() )
+		{
+			parent = parent.parent;
+		}
+		
+		return parent;
+	}
+	
+	this.getPercentage = function()
+	{
+		return getPercentage(this.magnitude / selectedNode.magnitude);
+	}
+	
+	this.getUnclassifiedPercentage = function()
+	{
+		var lastChild = this.children[this.children.length - 1];
+		
+		return getPercentage
+		(
+			(
+				this.baseMagnitude +
+				this.magnitude -
+				lastChild.magnitude -
+				lastChild.baseMagnitude
+			) / this.magnitude
+		) + '%';
+	}
+	
+	this.getUnclassifiedText = function()
+	{
+		return '[other '+ this.name + ']';
+	}
+	
+	this.getUncollapsed = function()
+	{
+		// recurse through collapsed children until uncollapsed node is found
+		
+		if ( this.getCollapse() )
+		{
+			return this.children[0].getUncollapsed();
+		}
+		else
+		{
+			return this;
+		}
+	}
+	
+	this.hasChildren = function()
+	{
+		return this.children.length && this.depth < maxAbsoluteDepth && this.magnitude;
+	}
+	
+	this.hasParent = function(parent)
+	{
+		if ( this.parent )
+		{
+			if ( this.parent == parent )
+			{
+				return true;
+			}
+			else
+			{
+				return this.parent.hasParent(parent);
+			}
+		}
+		else
+		{
+			return false;
+		}
+	}
+	
+	this.maxVisibleDepth = function(maxDepth)
+	{
+		var childInnerRadius;
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		var currentMaxDepth = depth;
+		
+		if ( this.hasChildren() && depth < maxDepth)
+		{
+			var lastChild = this.children[this.children.length - 1];
+			
+			if ( this.name == 'Pseudomonadaceae' )
+			{
+				var x = 3;
+			}
+			
+			if
+			(
+				lastChild.baseMagnitude + lastChild.magnitude <
+				this.baseMagnitude + this.magnitude
+			)
+			{
+				currentMaxDepth++;
+			}
+			
+			if ( compress )
+			{
+				childInnerRadius = compressedRadii[depth - 1];
+			}
+			else
+			{
+				childInnerRadius = (depth) / maxDepth;
+			}
+			
+			for ( var i = 0; i < this.children.length; i++ )
+			{
+				if
+				(//true ||
+					this.children[i].magnitude *
+					angleFactor *
+					(childInnerRadius + 1) *
+					gRadius >=
+					minWidth()
+				)
+				{
+					var childMaxDepth = this.children[i].maxVisibleDepth(maxDepth);
+					
+					if ( childMaxDepth > currentMaxDepth )
+					{
+						currentMaxDepth = childMaxDepth;
+					}
+				}
+			}
+		}
+		
+		return currentMaxDepth;
+	}
+	
+	this.resetLabelWidth = function()
+	{
+		var nameWidthOld = this.nameWidth;
+		
+		if ( true || ! this.radial )//&& fontSize != fontSizeLast )
+		{
+			var dim = context.measureText(this.name);
+			this.nameWidth = dim.width;
+		}
+		
+		if ( fontSize != fontSizeLast && this.labelWidth.end == nameWidthOld * labelWidthFudge )
+		{
+			// font size changed; adjust start of tween to match
+			
+			this.labelWidth.start = this.nameWidth * labelWidthFudge;
+		}
+		else
+		{
+			this.labelWidth.start = this.labelWidth.current();
+		}
+		
+		this.labelWidth.end = this.nameWidth * labelWidthFudge;
+	}
+	
+	this.restrictLabelWidth = function(width)
+	{
+		if ( width < this.labelWidth.end )
+		{
+			this.labelWidth.end = width;
+		}
+	}
+	
+	this.search = function()
+	{
+		this.isSearchResult = false;
+		this.searchResults = 0;
+		
+		if
+		(
+			! this.getCollapse() &&
+			search.value != '' &&
+			this.name.toLowerCase().indexOf(search.value.toLowerCase()) != -1
+		)
+		{
+			this.isSearchResult = true;
+			this.searchResults = 1;
+			nSearchResults++;
+		}
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.searchResults += this.children[i].search();
+		}
+		
+		return this.searchResults;
+	}
+	
+	this.searchResultChildren = function()
+	{
+		if ( this.isSearchResult )
+		{
+			return this.searchResults - 1;
+		}
+		else
+		{
+			return this.searchResults;
+		}
+	}
+	
+	this.setDepth = function(depth, depthCollapsed)
+	{
+		this.depth = depth;
+		this.depthCollapsed = depthCollapsed;
+		
+		if
+		(
+			this.children.length == 1 &&
+//			this.magnitude > 0 &&
+			this.children[0].magnitude == this.magnitude &&
+			( head.children.length > 1 || this.children[0].children.length )
+		)
+		{
+			this.collapse = true;
+		}
+		else
+		{
+			this.collapse = false;
+			depthCollapsed++;
+		}
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setDepth(depth + 1, depthCollapsed);
+		}
+	}
+	
+	this.setHighlightStyle = function()
+	{
+		context.lineWidth = highlightLineWidth;
+		
+		if ( this.hasChildren() || this != focusNode || this != highlightedNode )
+		{
+			context.strokeStyle = 'black';
+			context.fillStyle = "rgba(255, 255, 255, .3)";
+		}
+		else
+		{
+			context.strokeStyle = 'rgb(90,90,90)';
+			context.fillStyle = "rgba(155, 155, 155, .3)";
+		}
+	}
+	
+	this.setLabelWidth = function(node)
+	{
+		if ( ! shorten || this.radial )
+		{
+			return; // don't need to set width
+		}
+		
+		if ( node.hide )
+		{
+			alert('wtf');
+			return;
+		}
+		
+		var angle = (this.angleStart.end + this.angleEnd.end) / 2;
+		var a; // angle difference
+		
+		if ( node == selectedNode )
+		{
+			a = Math.abs(angle - node.angleOther);
+		}
+		else
+		{
+			a = Math.abs(angle - (node.angleStart.end + node.angleEnd.end) / 2);
+		}
+		
+		if ( a == 0 )
+		{
+			return;
+		}
+		
+		if ( a > Math.PI )
+		{
+			a = 2 * Math.PI - a;
+		}
+		
+		if ( node.radial || node == selectedNode )
+		{
+			var nodeLabelRadius;
+			
+			if ( node == selectedNode )
+			{
+				// radial 'other' label
+				
+				nodeLabelRadius = (node.children[0].radiusInner.end + 1) / 2;
+			}
+			else
+			{
+				nodeLabelRadius = (node.radiusInner.end + 1) / 2;
+			}
+			
+			if ( a < Math.PI / 2 )
+			{
+				var r = this.labelRadius.end * gRadius + .5 * fontSize
+				var hypotenuse = r / Math.cos(a);
+				var opposite = r * Math.tan(a);
+				var fontRadius = .8 * fontSize;
+				
+				if
+				(
+					nodeLabelRadius * gRadius < hypotenuse &&
+					this.labelWidth.end / 2 + fontRadius > opposite
+				)
+				{
+					this.labelWidth.end = 2 * (opposite - fontRadius);
+				}
+			}
+		}
+		else if
+		(
+			this.labelRadius.end == node.labelRadius.end &&
+			a < Math.PI / 4
+		)
+		{
+			// same radius with small angle; use circumferential approximation
+			
+			var dist = a * this.labelRadius.end * gRadius - fontSize * (1 - a * 4 / Math.PI) * 1.3;
+			
+			if ( this.labelWidth.end < dist )
+			{
+				node.restrictLabelWidth((dist - this.labelWidth.end / 2) * 2);
+			}
+			else if ( node.labelWidth.end < dist )
+			{
+				this.restrictLabelWidth((dist - node.labelWidth.end / 2) * 2);
+			}
+			else
+			{
+				// both labels reach halfway point; restrict both
+				
+				this.labelWidth.end = dist;
+				node.labelWidth.end = dist
+			}
+		}
+		else
+		{
+			var r1 = this.labelRadius.end * gRadius;
+			var r2 = node.labelRadius.end * gRadius;
+			
+			// first adjust the radii to account for the height of the font by shifting them
+			// toward each other
+			//
+			var fontFudge = .35 * fontSize;
+			//
+			if ( this.labelRadius.end < node.labelRadius.end )
+			{
+				r1 += fontFudge;
+				r2 -= fontFudge;
+			}
+			else if ( this.labelRadius.end > node.labelRadius.end )
+			{
+				r1 -= fontFudge;
+				r2 += fontFudge;
+			}
+			else
+			{
+				r1 -= fontFudge;
+				r2 -= fontFudge;
+			}
+			
+			var r1s = r1 * r1;
+			var r2s = r2 * r2;
+			
+			// distance between the centers of the two labels
+			//
+			var dist = Math.sqrt(r1s + r2s - 2 * r1 * r2 * Math.cos(a));
+			
+			// angle at our label center between our radius and the line to the other label center
+			//
+			var b = Math.acos((r1s + dist * dist - r2s) / (2 * r1 * dist));
+			
+			// distance from our label center to the intersection of the two tangents
+			//
+			var l1 = Math.sin(a + b - Math.PI / 2) * dist / Math.sin(Math.PI - a);
+			
+			// distance from other label center the the intersection of the two tangents
+			//
+			var l2 = Math.sin(Math.PI / 2 - b) * dist / Math.sin(Math.PI - a);
+			
+			l1 = Math.abs(l1) - .4 * fontSize;
+			l2 = Math.abs(l2) - .4 * fontSize;
+/*			
+			// amount to shorten the distances because of the height of the font
+			//
+			var l3 = 0;
+			var fontRadius = fontSize * .55;
+			//
+			if ( l1 < 0 || l2 < 0 )
+			{
+				var l4 = fontRadius / Math.tan(a);
+			l1 = Math.abs(l1);
+			l2 = Math.abs(l2);
+			
+				l1 -= l4;
+				l2 -= l4;
+			}
+			else
+			{
+				var c = Math.PI - a;
+				
+				l3 = fontRadius * Math.tan(c / 2);
+			}
+*/			
+			if ( this.labelWidth.end / 2 > l1 && node.labelWidth.end / 2 > l2 )
+			{
+				// shorten the farthest one from the intersection
+				
+				if ( l1 > l2 )
+				{
+					this.restrictLabelWidth(2 * (l1));// - l3 - fontRadius));
+				}
+				else
+				{
+					node.restrictLabelWidth(2 * (l2));// - l3 - fontRadius));
+				}
+			}/*
+			else if ( this.labelWidth.end / 2 > l1 + l3 && node.labelWidth.end / 2 > l2 - l3 )
+			{
+				node.restrictLabelWidth(2 * (l2 - l3));
+			}
+			else if ( this.labelWidth.end / 2 > l1 - l3 && node.labelWidth.end / 2 > l2 + l3 )
+			{
+				this.restrictLabelWidth(2 * (l1 - l3));
+			}*/
+		}
+	}
+	
+	this.setMagnitudes = function(baseMagnitude)
+	{
+		this.magnitude = this.getMagnitude();
+		this.baseMagnitude = baseMagnitude;
+		
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setMagnitudes(baseMagnitude);
+			baseMagnitude += this.children[i].magnitude;
+		}
+		
+		this.maxChildMagnitude = baseMagnitude;
+	}
+	
+	this.setMaxDepths = function()
+	{
+		this.maxDepth = this.depth;
+		this.maxDepthCollapsed = this.depthCollapsed;
+		
+		for ( i in this.children )
+		{
+			var child = this.children[i];
+			
+			child.setMaxDepths();
+			
+			if ( child.maxDepth > this.maxDepth )
+			{
+				this.maxDepth = child.maxDepth;
+			}
+			
+			if
+			(
+				child.maxDepthCollapsed > this.maxDepthCollapsed &&
+				(child.depth <= maxAbsoluteDepth || maxAbsoluteDepth == 0)
+			)
+			{
+				this.maxDepthCollapsed = child.maxDepthCollapsed;
+			}
+		}
+	}
+	
+	this.setTargetLabelRadius = function()
+	{
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		var index = depth - 2;
+		var labelOffset = labelOffsets[index];
+		
+		if ( this.radial )
+		{
+			//this.labelRadius.setTarget((this.radiusInner.end + 1) / 2);
+			var max =
+				depth == maxDisplayDepth ?
+				1 :
+				compressedRadii[index + 1];
+			
+			this.labelRadius.setTarget((compressedRadii[index] + max) / 2);
+		}
+		else
+		{
+			var radiusCenter;
+			var width;
+			
+			if ( compress )
+			{
+				if ( nLabelOffsets[index] > 1 )
+				{
+					this.labelRadius.setTarget
+					(
+						lerp
+						(
+							labelOffset + .75,
+							0,
+							nLabelOffsets[index] + .5,
+							compressedRadii[index],
+							compressedRadii[index + 1]
+						)
+					);
+				}
+				else
+				{
+					this.labelRadius.setTarget((compressedRadii[index] + compressedRadii[index + 1]) / 2);
+				}
+			}
+			else
+			{
+				radiusCenter =
+					nodeRadius * (depth - 1) +
+					nodeRadius / 2;
+				width = nodeRadius;
+				
+				this.labelRadius.setTarget
+				(
+					radiusCenter + width * ((labelOffset + 1) / (nLabelOffsets[index] + 1) - .5)
+				);
+			}
+		}
+		
+		if ( ! this.hide && ! this.keyed && nLabelOffsets[index] )
+		{
+			// check last and first labels in each track for overlap
+			
+			for ( var i = 0; i < maxDisplayDepth - 1; i++ )
+			{
+				for ( var j = 0; j <= nLabelOffsets[i]; j++ )
+				{
+					var last = labelLastNodes[i][j];
+					var first = labelFirstNodes[i][j];
+					
+					if ( last )
+					{
+						if ( j == nLabelOffsets[i] )
+						{
+							// last is radial
+							this.setLabelWidth(last);
+						}
+						else
+						{
+							last.setLabelWidth(this);
+						}
+					}
+					
+					if ( first )
+					{
+						if ( j == nLabelOffsets[i] )
+						{
+							this.setLabelWidth(first);
+						}
+						else
+						{
+							first.setLabelWidth(this);
+						}
+					}
+				}
+			}
+			
+			if ( selectedNode.canDisplayLabelOther )
+			{
+				this.setLabelWidth(selectedNode); // in case there is an 'other' label
+			}
+			
+			if ( this.radial )
+			{
+				// use the last 'track' of this depth for radial
+				
+				labelLastNodes[index][nLabelOffsets[index]] = this;
+				
+				if ( labelFirstNodes[index][nLabelOffsets[index]] == 0 )
+				{
+					labelFirstNodes[index][nLabelOffsets[index]] = this;
+				}
+			}
+			else
+			{
+				labelLastNodes[index][labelOffset] = this;
+				
+				// update offset
+				
+				labelOffsets[index] += 1;
+				
+				if ( labelOffsets[index] > nLabelOffsets[index] )
+				{
+					labelOffsets[index] -= nLabelOffsets[index];
+					
+					if ( !(nLabelOffsets[index] & 1) )
+					{
+						labelOffsets[index]--;
+					}
+				}
+				else if ( labelOffsets[index] == nLabelOffsets[index] )
+				{
+					labelOffsets[index] -= nLabelOffsets[index];
+					
+					if ( false && !(nLabelOffsets[index] & 1) )
+					{
+						labelOffsets[index]++;
+					}
+				}
+				
+				if ( labelFirstNodes[index][labelOffset] == 0 )
+				{
+					labelFirstNodes[index][labelOffset] = this;
+				}
+			}
+		}
+		else if ( this.hide )
+		{
+			this.labelWidth.end = 0;
+		}
+	}
+	
+	this.setTargets = function()
+	{
+		if ( this == selectedNode )
+		{
+			this.setTargetsSelected
+			(
+				0,
+				1,
+				lightnessBase,
+				false,
+				false
+			);
+			return;
+		}
+		
+		var depthRelative = this.getDepth() - selectedNode.getDepth();
+		
+		var parentOfSelected = selectedNode.hasParent(this);
+/*		(
+//			! this.getCollapse() &&
+			this.baseMagnitude <= selectedNode.baseMagnitude &&
+			this.baseMagnitude + this.magnitude >=
+			selectedNode.baseMagnitude + selectedNode.magnitude
+		);
+*/		
+		if ( parentOfSelected )
+		{
+			this.resetLabelWidth();
+		}
+		else
+		{
+			//context.font = fontNormal;
+			var dim = context.measureText(this.name);
+			this.nameWidth = dim.width;
+			//this.labelWidth.setTarget(this.labelWidth.end);
+			this.labelWidth.setTarget(0);
+		}
+		
+		// set angles
+		//
+		if ( this.baseMagnitude <= selectedNode.baseMagnitude )
+		{
+			this.angleStart.setTarget(0);
+		}
+		else
+		{
+			this.angleStart.setTarget(Math.PI * 2);
+		}
+		//
+		if
+		(
+			parentOfSelected ||
+			this.baseMagnitude + this.magnitude >=
+			selectedNode.baseMagnitude + selectedNode.magnitude
+		)
+		{
+			this.angleEnd.setTarget(Math.PI * 2);
+		}
+		else
+		{
+			this.angleEnd.setTarget(0);
+		}
+		
+		// children
+		//
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setTargets();
+		}
+		
+		if ( this.getDepth() <= selectedNode.getDepth() )
+		{
+			// collapse in
+			
+			this.radiusInner.setTarget(0);
+			
+			if ( parentOfSelected )
+			{
+				this.labelRadius.setTarget
+				(
+					(depthRelative) *
+					historySpacingFactor * fontSize / gRadius
+				);
+				//this.scale.setTarget(1 - (selectedNode.getDepth() - this.getDepth()) / 18); // TEMP
+			}
+			else
+			{
+				this.labelRadius.setTarget(0);
+				//this.scale.setTarget(1); // TEMP
+			}
+		}
+		else if ( depthRelative + 1 > maxDisplayDepth )
+		{
+			// collapse out
+			
+			this.radiusInner.setTarget(1);
+			this.labelRadius.setTarget(1);
+			//this.scale.setTarget(1); // TEMP
+		}
+		else
+		{
+			// don't collapse
+			
+			if ( compress )
+			{
+				this.radiusInner.setTarget(compressedRadii[depthRelative - 1]);
+			}
+			else
+			{
+				this.radiusInner.setTarget(nodeRadius * (depthRelative));
+			}
+			
+			//this.scale.setTarget(1); // TEMP
+			
+			if ( this == selectedNode )
+			{
+				this.labelRadius.setTarget(0);
+			}
+			else
+			{
+				if ( compress )
+				{
+					this.labelRadius.setTarget
+					(
+						(compressedRadii[depthRelative - 1] + compressedRadii[depthRelative]) / 2
+					);
+				}
+				else
+				{
+					this.labelRadius.setTarget(nodeRadius * (depthRelative) + nodeRadius / 2);
+				}
+			}
+		}
+		
+//		this.r.start = this.r.end;
+//		this.g.start = this.g.end;
+//		this.b.start = this.b.end;
+		
+		this.r.setTarget(255);
+		this.g.setTarget(255);
+		this.b.setTarget(255);
+
+		this.alphaLine.setTarget(0);
+		this.alphaArc.setTarget(0);
+		this.alphaWedge.setTarget(0);
+		this.alphaPattern.setTarget(0);
+		this.alphaOther.setTarget(0);
+		
+		if ( parentOfSelected && ! this.getCollapse() )
+		{
+			var alpha =
+			(
+				1 -
+				(selectedNode.getDepth() - this.getDepth()) /
+				(Math.floor((compress ? compressedRadii[0] : nodeRadius) * gRadius / (historySpacingFactor * fontSize) - .5) + 1)
+			);
+			
+			if ( alpha < 0 )
+			{
+				alpha = 0;
+			}
+			
+			this.alphaLabel.setTarget(alpha);
+			this.radial = false;
+		}
+		else
+		{
+			this.alphaLabel.setTarget(0);
+		}
+		
+		this.hideAlonePrev = this.hideAlone;
+		this.hidePrev = this.hide;
+		
+		if ( parentOfSelected )
+		{
+			this.hideAlone = false;
+			this.hide = false;
+		}
+		
+		if ( this.getParent() == selectedNode.getParent() )
+		{
+			this.hiddenEnd = null;
+		}
+		
+		this.radialPrev = this.radial;
+	}
+	
+	this.setTargetsSelected = function(hueMin, hueMax, lightness, hide, nextSiblingHidden)
+	{
+		var collapse = this.getCollapse();
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		var canDisplayChildLabels = false;
+		var lastChild;
+		
+		if ( this.hasChildren() )//&& ! hide )
+		{
+			lastChild = this.children[this.children.length - 1];
+			this.hideAlone = true;
+		}
+		else
+		{
+			this.hideAlone = false;
+		}
+		
+		// set child wedges
+		//
+		for ( var i = 0; i < this.children.length; i++ )
+		{
+			this.children[i].setTargetWedge();
+			
+			if
+			(
+				! this.children[i].hide &&
+				( collapse || depth < maxDisplayDepth ) &&
+				this.depth < maxAbsoluteDepth
+			)
+			{
+				canDisplayChildLabels = true;
+				this.hideAlone = false;
+			}
+		}
+		
+		if ( this == selectedNode || lastChild && lastChild.angleEnd.end < this.angleEnd.end - .01)
+		{
+			this.hideAlone = false;
+		}
+		
+		if ( this.hideAlonePrev == undefined )
+		{
+			this.hideAlonePrev = this.hideAlone;
+		}
+		
+		if ( this == selectedNode )
+		{
+			var otherArc = 
+				angleFactor *
+				(
+					this.baseMagnitude + this.magnitude -
+					lastChild.baseMagnitude - lastChild.magnitude
+				);
+			this.canDisplayLabelOther =
+				otherArc *
+				(this.children[0].radiusInner.end + 1) * gRadius >=
+				minWidth();
+			
+			this.keyUnclassified = false;
+			
+			if ( this.canDisplayLabelOther )
+			{
+				this.angleOther = Math.PI * 2 - otherArc / 2;
+			}
+			else if ( otherArc > 0.0000000001 )
+			{
+				this.keyUnclassified = true;
+				keys++;
+			}
+			
+			this.angleStart.setTarget(0);
+			this.angleEnd.setTarget(Math.PI * 2);
+			this.radiusInner.setTarget(0);
+			this.hidePrev = this.hide;
+			this.hide = false;
+			this.hideAlonePrev = this.hideAlone;
+			this.hideAlone = false;
+			this.keyed = false;
+		}
+		
+		if ( hueMax - hueMin > 1 / 12 )
+		{
+			hueMax = hueMin + 1 / 12;
+		}
+		
+		// set lightness
+		//
+		if ( ! ( hide || this.hideAlone ) )
+		{
+			if ( useHue() )
+			{
+				lightness = (lightnessBase + lightnessMax) / 2;
+			}
+			else
+			{
+				lightness = lightnessBase + (depth - 1) * lightnessFactor;
+				
+				if ( lightness > lightnessMax )
+				{
+					lightness = lightnessMax;
+				}
+			}
+		}
+		
+		if ( hide )
+		{
+			this.hide = true;
+		}
+		
+		if ( this.hidePrev == undefined )
+		{
+			this.hidePrev = this.hide;
+		}
+		
+		var hiddenStart = -1;
+		var hiddenHueNumer = 0;
+		var hiddenHueDenom = 0;
+		var i = 0;
+		
+		if ( ! this.hide )
+		{
+			this.hiddenEnd = null;
+		}
+		
+		while ( true )
+		{
+			if ( ! this.hideAlone && ! hide && ( i == this.children.length || ! this.children[i].hide ) )
+			{
+				// reached a non-hidden child or the end; set targets for
+				// previous group of hidden children (if any) using their
+				// average hue
+				
+				if ( hiddenStart != -1 )
+				{
+					var hiddenHue = hiddenHueDenom ? hiddenHueNumer / hiddenHueDenom : hueMin;
+					
+					for ( var j = hiddenStart; j < i; j++ )
+					{
+						this.children[j].setTargetsSelected
+						(
+							hiddenHue,
+							null,
+							lightness,
+							false,
+							j < i - 1
+						);
+						
+						this.children[j].hiddenEnd = null;
+					}
+					
+					this.children[hiddenStart].hiddenEnd = i - 1;
+				}
+			}
+			
+			if ( i == this.children.length )
+			{
+				break;
+			}
+			
+			var child = this.children[i];
+			var childHueMin;
+			var childHueMax;
+			
+			if ( this.magnitude > 0 && ! this.hide && ! this.hideAlone )
+			{
+				if ( useHue() )
+				{
+					childHueMin = child.hues[currentDataset];
+				}
+				else if ( this == selectedNode )
+				{
+					var min = 0.0;
+					var max = 1.0;
+					
+					if ( this.children.length > 6 )
+					{
+						childHueMin = lerp((1 - Math.pow(1 - i / this.children.length, 1.4)) * .95, 0, 1, min, max);
+						childHueMax = lerp((1 - Math.pow(1 - (i + .55) / this.children.length, 1.4)) * .95, 0, 1, min, max);
+					}
+					else
+					{
+						childHueMin = lerp(i / this.children.length, 0, 1, min, max);
+						childHueMax = lerp((i + .55) / this.children.length, 0, 1, min, max);
+					}
+				}
+				else
+				{
+					childHueMin = lerp
+					(
+						child.baseMagnitude,
+						this.baseMagnitude, 
+						this.baseMagnitude + this.magnitude,
+						hueMin,
+						hueMax
+					);
+					childHueMax = lerp
+					(
+						child.baseMagnitude + child.magnitude * .99,
+						this.baseMagnitude,
+						this.baseMagnitude + this.magnitude,
+						hueMin,
+						hueMax
+					);
+				}
+			}
+			else
+			{
+				childHueMin = hueMin;
+				childHueMax = hueMax;
+			}
+			
+			if ( ! this.hideAlone && ! hide && ! this.hide && child.hide )
+			{
+				if ( hiddenStart == -1 )
+				{
+					hiddenStart = i;
+				}
+				
+				if ( useHue() )
+				{
+					hiddenHueNumer += childHueMin * child.magnitude;
+					hiddenHueDenom += child.magnitude;
+				}
+				else
+				{
+					hiddenHueNumer += childHueMin;
+					hiddenHueDenom++;
+				}
+			}
+			else
+			{
+				hiddenStart = -1;
+				
+				this.children[i].setTargetsSelected
+				(
+					childHueMin,
+					childHueMax,
+					lightness,
+					hide || this.keyed || this.hideAlone || this.hide && ! collapse,
+					false
+				);
+			}
+			
+			i++;
+		}
+		
+	 	if ( this.hue && this.magnitude )
+	 	{
+		 	this.hue.setTarget(this.hues[currentDataset]);
+			
+			if ( this.attributes[magnitudeIndex][lastDataset] == 0 )
+			{
+				this.hue.start = this.hue.end;
+			}
+		}
+	 	
+		this.radialPrev = this.radial;
+		
+		if ( this == selectedNode )
+		{
+			this.resetLabelWidth();
+			this.labelWidth.setTarget(this.nameWidth * labelWidthFudge);
+			this.alphaWedge.setTarget(0);
+			this.alphaLabel.setTarget(1);
+			this.alphaOther.setTarget(1);
+			this.alphaArc.setTarget(0);
+			this.alphaLine.setTarget(0);
+			this.alphaPattern.setTarget(0);
+			this.r.setTarget(255);
+			this.g.setTarget(255);
+			this.b.setTarget(255);
+			this.radial = false;
+			this.labelRadius.setTarget(0);
+		}
+		else
+		{
+			var rgb = hslToRgb
+			(
+				hueMin,
+				saturation,
+				lightness
+			);
+			
+			this.r.setTarget(rgb.r);
+			this.g.setTarget(rgb.g);
+			this.b.setTarget(rgb.b);
+			this.alphaOther.setTarget(0);
+			
+			this.alphaWedge.setTarget(1);
+			
+			if ( this.hide || this.hideAlone )
+			{
+				this.alphaPattern.setTarget(1);
+			}
+			else
+			{
+				this.alphaPattern.setTarget(0);
+			}
+			
+			// set radial
+			//
+			if ( ! ( hide || this.hide ) )//&& ! this.keyed )
+			{
+				if ( this.hideAlone )
+				{
+					this.radial = true;
+				}
+				else if ( false && canDisplayChildLabels )
+				{
+					this.radial = false;
+				}
+				else
+				{
+					this.radial = true;
+					
+					if ( this.hasChildren() && depth < maxDisplayDepth )
+					{
+						var lastChild = this.children[this.children.length - 1];
+						
+						if
+						(
+							lastChild.angleEnd.end == this.angleEnd.end ||
+							(
+								(this.angleStart.end + this.angleEnd.end) / 2 -
+								lastChild.angleEnd.end
+							) * (this.radiusInner.end + 1) * gRadius * 2 <
+							minWidth()
+						)
+						{
+							this.radial = false;
+						}
+					}
+				}
+			}
+			
+			// set alphaLabel
+			//
+			if
+			(
+				collapse ||
+				hide ||
+				this.hide ||
+				this.keyed ||
+				depth > maxDisplayDepth ||
+				! this.canDisplayDepth()
+			)
+			{
+				this.alphaLabel.setTarget(0);
+			}
+			else
+			{
+				if
+				(
+					(this.radial || nLabelOffsets[depth - 2])
+				)
+				{
+					this.alphaLabel.setTarget(1);
+				}
+				else
+				{
+					this.alphaLabel.setTarget(0);
+					
+					if ( this.radialPrev )
+					{
+						this.alphaLabel.start = 0;
+					}
+				}
+			}
+			
+			// set alphaArc
+			//
+			if
+			(
+				collapse ||
+				hide ||
+				depth > maxDisplayDepth ||
+				! this.canDisplayDepth()
+			)
+			{
+				this.alphaArc.setTarget(0);
+			}
+			else
+			{
+				this.alphaArc.setTarget(1);
+			}
+			
+			// set alphaLine
+			//
+			if
+			(
+				hide ||
+				this.hide && nextSiblingHidden ||
+				depth > maxDisplayDepth ||
+				! this.canDisplayDepth()
+			)
+			{
+				this.alphaLine.setTarget(0);
+			}
+			else
+			{
+				this.alphaLine.setTarget(1);
+			}
+			
+			//if (  ! this.radial )
+			{
+				this.resetLabelWidth();
+			}
+			
+			// set labelRadius target
+			//
+			if ( collapse )
+			{
+				this.labelRadius.setTarget(this.radiusInner.end);
+			}
+			else
+			{
+				if ( depth > maxDisplayDepth || ! this.canDisplayDepth() )
+				{
+					this.labelRadius.setTarget(1);
+				}
+				else
+				{
+					this.setTargetLabelRadius();
+				}
+			}
+		}
+	}
+	
+	this.setTargetWedge = function()
+	{
+		var depth = this.getDepth() - selectedNode.getDepth() + 1;
+		
+		// set angles
+		//
+		var baseMagnitudeRelative = this.baseMagnitude - selectedNode.baseMagnitude;
+		//
+		this.angleStart.setTarget(baseMagnitudeRelative * angleFactor);
+		this.angleEnd.setTarget((baseMagnitudeRelative + this.magnitude) * angleFactor);
+		
+		// set radiusInner
+		//
+		if ( depth > maxDisplayDepth || ! this.canDisplayDepth() )
+		{
+			this.radiusInner.setTarget(1);
+		}
+		else
+		{
+			if ( compress )
+			{
+				this.radiusInner.setTarget(compressedRadii[depth - 2]);
+			}
+			else
+			{
+				this.radiusInner.setTarget(nodeRadius * (depth - 1));
+			}
+		}
+		
+		if ( this.hide != undefined )
+		{
+			this.hidePrev = this.hide;
+		}
+		
+		if ( this.hideAlone != undefined )
+		{
+			this.hideAlonePrev = this.hideAlone;
+		}
+		
+		// set hide
+		//
+		if
+		(
+			(this.angleEnd.end - this.angleStart.end) *
+			(this.radiusInner.end * gRadius + gRadius) <
+			minWidth()
+		)
+		{
+			if ( depth == 2 && ! this.getCollapse() && this.depth <= maxAbsoluteDepth )
+			{
+				this.keyed = true;
+				keys++;
+				this.hide = false;
+				
+				var percentage = this.getPercentage();
+				this.keyLabel = this.name + '   ' + percentage + '%';
+				var dim = context.measureText(this.keyLabel);
+				this.keyNameWidth = dim.width;
+			}
+			else
+			{
+				this.keyed = false;
+				this.hide = depth > 2;
+			}
+		}
+		else
+		{
+			this.keyed = false;
+			this.hide = false;
+		}
+	}
+	
+	this.shortenLabel = function()
+	{
+		var label = this.name;
+		
+		var labelWidth = this.nameWidth;
+		var maxWidth = this.labelWidth.current();
+		var minEndLength = 0;
+		
+		if ( labelWidth > maxWidth && label.length > minEndLength * 2 )
+		{
+			var endLength =
+				Math.floor((label.length - 1) * maxWidth / labelWidth / 2);
+			
+			if ( endLength < minEndLength )
+			{
+				endLength = minEndLength;
+			}
+			
+			return (
+				label.substring(0, endLength) +
+				'...' +
+				label.substring(label.length - endLength));
+		}
+		else
+		{
+			return label;
+		}
+	}
+	
+/*	this.shouldAddSearchResultsString = function()
+	{
+		if ( this.isSearchResult )
+		{
+			return this.searchResults > 1;
+		}
+		else
+		{
+			return this.searchResults > 0;
+		}
+	}
+*/	
+	this.sort = function()
+	{
+		this.children.sort(function(a, b){return b.getMagnitude() - a.getMagnitude()});
+		
+		for (var i = 0; i < this.children.length; i++)
+		{
+			this.children[i].sort();
+		}
+	}
+}
+
+var options;
+
+function addOptionElement(position, innerHTML, title)
+{
+	var div = document.createElement("div");
+//	div.style.position = 'absolute';
+//	div.style.top = position + 'px';
+	div.innerHTML = innerHTML;
+//	div.style.display = 'block';
+	div.style.padding = '2px';
+	
+	if ( title )
+	{
+		div.title = title;
+	}
+	
+	options.appendChild(div);
+	var height = 0;//div.clientHeight;
+	return position + height;
+}
+
+function addOptionElements(hueName, hueDefault)
+{
+	options = document.createElement('div');
+	options.style.position = 'absolute';
+	options.style.top = '0px';
+	options.addEventListener('mousedown', function(e) {mouseClick(e)}, false);
+//	options.onmouseup = function(e) {mouseUp(e)}
+	document.body.appendChild(options);
+	
+	document.body.style.font = '11px sans-serif';
+	var position = 5;
+	
+	details = document.createElement('div');
+	details.style.position = 'absolute';
+	details.style.top = '1%';
+	details.style.right = '2%';
+	details.style.textAlign = 'right';
+	document.body.insertBefore(details, canvas);
+//		<div id="details" style="position:absolute;top:1%;right:2%;text-align:right;">
+
+	details.innerHTML = '\
+<span id="detailsName" style="font-weight:bold"></span> \
+<input type="button" id="detailsExpand" onclick="expand(focusNode);"\
+value="↔" title="Expand this wedge to become the new focus of the chart"/><br/>\
+<div id="detailsInfo" style="float:right"></div>';
+
+	keyControl = document.createElement('input');
+	keyControl.type = 'button';
+	keyControl.value = showKeys ? 'x' : '…';
+	keyControl.style.position = '';
+	keyControl.style.position = 'fixed';
+	keyControl.style.visibility = 'hidden';
+	
+	document.body.insertBefore(keyControl, canvas);
+	
+	var logoElement = document.getElementById('logo');
+	
+	if ( logoElement )
+	{
+		logoImage = logoElement.src;
+	}
+	else
+	{
+		logoImage = 'http://marbl.github.io/Krona/img/logo-med.png';
+	}
+	
+//	document.getElementById('options').style.fontSize = '9pt';
+	position = addOptionElement
+	(
+		position,
+'<a style="margin:2px" target="_blank" href="https://github.com/marbl/Krona/wiki"><img style="vertical-align:middle;width:108px;height:30px;" src="' + logoImage + '"/></a><input type="button" id="back" value="←" title="Go back (Shortcut: ←)"/>\
+<input type="button" id="forward" value="→" title="Go forward (Shortcut: →)"/> \
+ Search: <input type="text" id="search"/>\
+<input id="searchClear" type="button" value="x" onclick="clearSearch()"/> \
+<span id="searchResults"></span>'
+	);
+	
+	if ( datasets > 1 )
+	{
+		var size = datasets < datasetSelectSize ? datasets : datasetSelectSize;
+		
+		var select =
+			'<table style="border-collapse:collapse;padding:0px"><tr><td style="padding:0px">' +
+			'<select id="datasets" style="min-width:100px" size="' + size + '" onchange="onDatasetChange()">';
+		
+		for ( var i = 0; i < datasetNames.length; i++ )
+		{
+			select += '<option>' + datasetNames[i] + '</option>';
+		}
+		
+		select +=
+			'</select></td><td style="vertical-align:top;padding:1px;">' +
+			'<input style="display:block" title="Previous dataset (Shortcut: ↑)" id="prevDataset" type="button" value="↑" onclick="prevDataset()" disabled="true"/>' +
+			'<input title="Next dataset (Shortcut: ↓)" id="nextDataset" type="button" value="↓" onclick="nextDataset()"/><br/></td>' +
+			'<td style="padding-top:1px;vertical-align:top"><input title="Switch to the last dataset that was viewed (Shortcut: TAB)" id="lastDataset" type="button" style="font:11px Times new roman" value="last" onclick="selectLastDataset()"/></td></tr></table>';
+		
+		position = addOptionElement(position + 5, select);
+		
+		datasetDropDown = document.getElementById('datasets');
+		datasetButtonLast = document.getElementById('lastDataset');
+		datasetButtonPrev = document.getElementById('prevDataset');
+		datasetButtonNext = document.getElementById('nextDataset');
+		
+		position += datasetDropDown.clientHeight;
+	}
+	
+	position = addOptionElement
+	(
+		position + 5,
+'<input type="button" id="maxAbsoluteDepthDecrease" value="-"/>\
+<span id="maxAbsoluteDepth"></span>\
+ <input type="button" id="maxAbsoluteDepthIncrease" value="+"/> Max depth',
+'Maximum depth to display, counted from the top level \
+and including collapsed wedges.'
+	);
+	
+	position = addOptionElement
+	(
+		position,
+'<input type="button" id="fontSizeDecrease" value="-"/>\
+<span id="fontSize"></span>\
+ <input type="button" id="fontSizeIncrease" value="+"/> Font size'
+	);
+	
+	position = addOptionElement
+	(
+		position,
+'<input type="button" id="radiusDecrease" value="-"/>\
+<input type="button" id="radiusIncrease" value="+"/> Chart size'
+	);
+	
+	if ( hueName )
+	{
+		hueDisplayName = attributes[attributeIndex(hueName)].displayName;
+		
+		position = addOptionElement
+		(
+			position + 5,
+			'<input type="checkbox" id="useHue" style="float:left" ' +
+			'/><div>Color by<br/>' + hueDisplayName +
+			'</div>'
+		);
+		
+		useHueCheckBox = document.getElementById('useHue');
+		useHueCheckBox.checked = hueDefault;
+		useHueCheckBox.onclick = handleResize;
+		useHueCheckBox.onmousedown = suppressEvent;
+	}
+	/*
+	position = addOptionElement
+	(
+		position + 5,
+		' <input type="checkbox" id="shorten" checked="checked" />Shorten labels</div>',
+		'Prevent labels from overlapping by shortening them'
+	);
+	
+	position = addOptionElement
+	(
+		position,
+		' <input type="checkbox" id="compress" checked="checked" />Compress',
+		'Compress wedges if needed to show the entire depth'
+	);
+	*/
+	position = addOptionElement
+	(
+		position,
+		'<input type="checkbox" id="collapse" checked="checked" />Collapse',
+		'Collapse wedges that are redundant (entirely composed of another wedge)'
+	);
+	
+	position = addOptionElement
+	(
+		position + 5,
+		'<input type="button" id="snapshot" value="Snapshot"/>',
+'Render the current view as SVG (Scalable Vector Graphics), a publication-\
+quality format that can be printed and saved (see Help for browser compatibility)'
+	);
+	
+	position = addOptionElement
+	(
+		position + 5,
+'<input type="button" id="linkButton" value="Link"/>\
+<input type="text" size="30" id="linkText"/>',
+'Show a link to this view that can be copied for bookmarking or sharing'
+	);
+	
+	position = addOptionElement
+	(
+		position + 5,
+'<input type="button" id="help" value="?"\
+onclick="window.open(\'https://github.com/marbl/Krona/wiki/Browsing%20Krona%20charts\', \'help\')"/>',
+'Help'
+	);
+}
+
+function arrow(angleStart, angleEnd, radiusInner)
+{
+	if ( context.globalAlpha == 0 )
+	{
+		return;
+	}
+	
+	var angleCenter = (angleStart + angleEnd) / 2;
+	var radiusArrowInner = radiusInner - gRadius / 10;//nodeRadius * gRadius;
+	var radiusArrowOuter = gRadius * 1.1;//(1 + nodeRadius);
+	var radiusArrowCenter = (radiusArrowInner + radiusArrowOuter) / 2;
+	var pointLength = (radiusArrowOuter - radiusArrowInner) / 5;
+	
+	context.fillStyle = highlightFill;
+	context.lineWidth = highlightLineWidth;
+	
+	// First, mask out the first half of the arrow.  This will prevent the tips
+	// from superimposing if the arrow goes most of the way around the circle.
+	// Masking is done by setting the clipping region to the inverse of the
+	// half-arrow, which is defined by cutting the half-arrow out of a large
+	// rectangle
+	//
+	context.beginPath();
+	context.arc(0, 0, radiusInner, angleCenter, angleEnd, false);
+	context.lineTo
+	(
+		radiusArrowInner * Math.cos(angleEnd),
+		radiusArrowInner * Math.sin(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowCenter * Math.cos(angleEnd) - pointLength * Math.sin(angleEnd),
+		radiusArrowCenter * Math.sin(angleEnd) + pointLength * Math.cos(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowOuter * Math.cos(angleEnd),
+		radiusArrowOuter * Math.sin(angleEnd)
+	);
+	context.arc(0, 0, gRadius, angleEnd, angleCenter, true);
+	context.closePath();
+	context.moveTo(-imageWidth, -imageHeight);
+	context.lineTo(imageWidth, -imageHeight);
+	context.lineTo(imageWidth, imageHeight);
+	context.lineTo(-imageWidth, imageHeight);
+	context.closePath();
+	context.save();
+	context.clip();
+	
+	// Next, draw the other half-arrow with the first half masked out
+	//
+	context.beginPath();
+	context.arc(0, 0, radiusInner, angleCenter, angleStart, true);
+	context.lineTo
+	(
+		radiusArrowInner * Math.cos(angleStart),
+		radiusArrowInner * Math.sin(angleStart)
+	);
+	context.lineTo
+	(
+		radiusArrowCenter * Math.cos(angleStart) + pointLength * Math.sin(angleStart),
+		radiusArrowCenter * Math.sin(angleStart) - pointLength * Math.cos(angleStart)
+	);
+	context.lineTo
+	(
+		radiusArrowOuter * Math.cos(angleStart),
+		radiusArrowOuter * Math.sin(angleStart)
+	);
+	context.arc(0, 0, gRadius, angleStart, angleCenter, false);
+	context.fill();
+	context.stroke();
+	
+	// Finally, remove the clipping region and draw the first half-arrow.  This
+	// half is extended slightly to fill the seam.
+	//
+	context.restore();
+	context.beginPath();
+	context.arc(0, 0, radiusInner, angleCenter - 2 / (2 * Math.PI * radiusInner), angleEnd, false);
+	context.lineTo
+	(
+		radiusArrowInner * Math.cos(angleEnd),
+		radiusArrowInner * Math.sin(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowCenter * Math.cos(angleEnd) - pointLength * Math.sin(angleEnd),
+		radiusArrowCenter * Math.sin(angleEnd) + pointLength * Math.cos(angleEnd)
+	);
+	context.lineTo
+	(
+		radiusArrowOuter * Math.cos(angleEnd),
+		radiusArrowOuter * Math.sin(angleEnd)
+	);
+	context.arc(0, 0, gRadius, angleEnd, angleCenter - 2 / (2 * Math.PI * gRadius), true);
+	context.fill();
+	context.stroke();
+}
+
+function attributeIndex(aname)
+{
+	for ( var i = 0 ; i < attributes.length; i++ )
+	{
+		if ( aname == attributes[i].name )
+		{
+			return i;
+		}
+	}
+	
+	return null;
+}
+
+function checkHighlight()
+{
+	var lastHighlightedNode = highlightedNode;
+	var lastHighlightingHidden = highlightingHidden;
+	
+	highlightedNode = selectedNode;
+	resetKeyOffset();
+	
+	if ( progress == 1 )
+	{
+		selectedNode.checkHighlight();
+		if ( selectedNode.getParent() )
+		{
+			selectedNode.getParent().checkHighlightCenter();
+		}
+		
+		focusNode.checkHighlightMap();
+	}
+	
+	if ( highlightedNode != selectedNode )
+	{
+		if ( highlightedNode == focusNode )
+		{
+//			canvas.style.display='none';
+//			window.resizeBy(1,0);
+//			canvas.style.cursor='ew-resize';
+//			window.resizeBy(-1,0);
+//			canvas.style.display='inline';
+		}
+		else
+		{
+//			canvas.style.cursor='pointer';
+		}
+	}
+	else
+	{
+//		canvas.style.cursor='auto';
+	}
+	
+	if
+	(
+		(
+			true ||
+			highlightedNode != lastHighlightedNode ||
+			highlightingHidden != highlightingHiddenLast
+		) &&
+		progress == 1
+	)
+	{
+		draw(); // TODO: handle in update()
+	}
+}
+
+function checkSelectedCollapse()
+{
+	var newNode = selectedNode;
+	
+	while ( newNode.getCollapse() )
+	{
+		newNode = newNode.children[0];
+	}
+	
+	if ( newNode.children.length == 0 )
+	{
+		newNode = newNode.getParent();
+	}
+	
+	if ( newNode != selectedNode )
+	{
+		selectNode(newNode);
+	}
+}
+
+function clearSearch()
+{
+	if ( search.value != '' )
+	{
+		search.value = '';
+		onSearchChange();
+	}
+}
+
+function createSVG()
+{
+	svgNS = "http://www.w3.org/2000/svg";
+	var SVG = {};
+	SVG.xlinkns = "http://www.w3.org/1999/xlink";
+	
+	var newSVG = document.createElementNS(svgNS, "svg:svg");
+	
+	newSVG.setAttribute("id", "canvas");
+	// How big is the canvas in pixels
+	newSVG.setAttribute("width", '100%');
+	newSVG.setAttribute("height", '100%');
+	// Set the coordinates used by drawings in the canvas
+//	newSVG.setAttribute("viewBox", "0 0 " + imageWidth + " " + imageHeight);
+	// Define the XLink namespace that SVG uses
+	newSVG.setAttributeNS
+	(
+		"http://www.w3.org/2000/xmlns/",
+		"xmlns:xlink",
+		SVG.xlinkns
+	);
+	
+	return newSVG;
+}
+
+function degrees(radians)
+{
+	return radians * 180 / Math.PI;
+}
+
+function draw()
+{
+	tweenFrames++;
+	//resize();
+//	context.fillRect(0, 0, imageWidth, imageHeight);
+	context.clearRect(0, 0, imageWidth, imageHeight);
+	
+	context.font = fontNormal;
+	context.textBaseline = 'middle';
+	
+	//context.strokeStyle = 'rgba(0, 0, 0, 0.3)';
+	context.translate(centerX, centerY);
+	
+	resetKeyOffset();
+	
+	head.draw(false, false); // draw pie slices
+	head.draw(true, false); // draw labels
+	
+	var pathRoot = selectedNode;
+	
+	if ( focusNode != 0 && focusNode != selectedNode )
+	{
+		context.globalAlpha = 1;
+		focusNode.drawHighlight(true);
+		pathRoot = focusNode;
+	}
+	
+	if
+	(
+		highlightedNode &&
+		highlightedNode.getDepth() >= selectedNode.getDepth() &&
+		highlightedNode != focusNode
+	)
+	{
+		if
+		(
+			progress == 1 &&
+			highlightedNode != selectedNode &&
+			(
+				highlightedNode != focusNode ||
+				focusNode.children.length > 0
+			)
+		)
+		{
+			context.globalAlpha = 1;
+			highlightedNode.drawHighlight(true);
+		}
+		
+		//pathRoot = highlightedNode;
+	}
+	else if
+	(
+		progress == 1 &&
+		highlightedNode.getDepth() < selectedNode.getDepth()
+	)
+	{
+		context.globalAlpha = 1;
+		highlightedNode.drawHighlightCenter();
+	}
+	
+	if ( quickLook && false) // TEMP
+	{
+		context.globalAlpha = 1 - progress / 2;
+		selectedNode.drawHighlight(true);
+	}
+	else if ( progress < 1 )//&& zoomOut() )
+	{
+		if ( !zoomOut)//() )
+		{
+			context.globalAlpha = selectedNode.alphaLine.current();
+			selectedNode.drawHighlight(true);
+		}
+		else if ( selectedNodeLast )
+		{
+			context.globalAlpha = 1 - 4 * Math.pow(progress - .5, 2);
+			selectedNodeLast.drawHighlight(false);
+		}
+	}
+	
+	drawDatasetName();
+	
+	//drawHistory();
+	
+	context.translate(-centerX, -centerY);
+	context.globalAlpha = 1;
+	
+	mapRadius =
+		(imageHeight / 2 - details.clientHeight - details.offsetTop) /
+		(pathRoot.getDepth() - 1) * 3 / 4 / 2;
+	
+	if ( mapRadius > maxMapRadius )
+	{
+		mapRadius = maxMapRadius;
+	}
+	
+	mapBuffer = mapRadius / 2;
+	
+	//context.font = fontNormal;
+	pathRoot.drawMap(pathRoot);
+	
+	if ( hueDisplayName && useHue() )
+	{
+		drawLegend();
+	}
+}
+
+function drawBubble(angle, radius, width, radial, flip)
+{
+	var height = fontSize * 2;
+	var x;
+	var y;
+	
+	width = width + fontSize;
+	
+	if ( radial )
+	{
+		y = -fontSize;
+		
+		if ( flip )
+		{
+			x = radius - width + fontSize / 2;
+		}
+		else
+		{
+			x = radius - fontSize / 2;
+		}
+	}
+	else
+	{
+		x = -width / 2;
+		y = -radius - fontSize;
+	}
+	
+	if ( snapshotMode )
+	{
+		drawBubbleSVG(x + centerX, y + centerY, width, height, fontSize, angle);
+	}
+	else
+	{
+		drawBubbleCanvas(x, y, width, height, fontSize, angle);
+	}
+}
+
+function drawBubbleCanvas(x, y, width, height, radius, rotation)
+{
+	context.strokeStyle = 'black';
+	context.lineWidth = highlightLineWidth;
+	context.fillStyle = 'rgba(255, 255, 255, .75)';
+	context.rotate(rotation);
+	roundedRectangle(x, y, width, fontSize * 2, fontSize);
+	context.fill();
+	context.stroke();
+	context.rotate(-rotation);
+}
+
+function drawBubbleSVG(x, y, width, height, radius, rotation)
+{
+	svg +=
+		'<rect x="' + x + '" y="' + y +
+		'" width="' + width +
+		'" height="' + height +
+		'" rx="' + radius +
+		'" ry="' + radius +
+		'" fill="rgba(255, 255, 255, .75)' +
+		'" class="highlight" ' +
+		'transform="rotate(' +
+		degrees(rotation) + ',' + centerX + ',' + centerY +
+		')"/>';
+}
+
+function drawDatasetName()
+{
+	var alpha = datasetAlpha.current();
+	
+	if ( alpha > 0 )
+	{
+		var radius = gRadius * compressedRadii[0] / -2;
+		
+		if ( alpha > 1 )
+		{
+			alpha = 1;
+		}
+		
+		context.globalAlpha = alpha;
+		
+		drawBubble(0, -radius, datasetWidths[currentDataset], false, false);
+		drawText(datasetNames[currentDataset], 0, radius, 0, 'center', true);
+	}
+}
+
+function drawHistory()
+{
+	var alpha = 1;
+	context.textAlign = 'center';
+	
+	for ( var i = 0; i < nodeHistoryPosition && alpha > 0; i++ )
+	{
+		
+		context.globalAlpha = alpha - historyAlphaDelta * tweenFactor;
+		context.fillText
+		(
+			nodeHistory[nodeHistoryPosition - i - 1].name,
+			0,
+			(i + tweenFactor) * historySpacingFactor * fontSize - 1
+		);
+		
+		if ( alpha > 0 )
+		{
+			alpha -= historyAlphaDelta;
+		}
+	}
+	
+	context.globalAlpha = 1;
+}
+
+function drawLegend()
+{
+	var left = imageWidth * .01;
+	var width = imageHeight * .0265;
+	var height = imageHeight * .15;
+	var top = imageHeight - fontSize * 3.5 - height;
+	var textLeft = left + width + fontSize / 2;
+	
+	context.fillStyle = 'black';
+	context.textAlign = 'start';
+	context.font = fontNormal;
+//	context.fillText(valueStartText, textLeft, top + height);
+//	context.fillText(valueEndText, textLeft, top);
+	context.fillText(hueDisplayName, left, imageHeight - fontSize * 1.5);
+	
+	var gradient = context.createLinearGradient(0, top + height, 0, top);
+	
+	for ( var i = 0; i < hueStopPositions.length; i++ )
+	{
+		gradient.addColorStop(hueStopPositions[i], hueStopHsl[i]);
+		
+		var textY = top + (1 - hueStopPositions[i]) * height;
+		
+		if
+		(
+			i == 0 ||
+			i == hueStopPositions.length - 1 ||
+			textY > top + fontSize && textY < top + height - fontSize
+		)
+		{
+			context.fillText(hueStopText[i], textLeft, textY);
+		}
+	}
+	
+	context.fillStyle = gradient;
+	context.fillRect(left, top, width, height);
+	context.lineWidth = thinLineWidth;
+	context.strokeRect(left, top, width, height);
+}
+
+function drawLegendSVG()
+{
+	var left = imageWidth * .01;
+	var width = imageHeight * .0265;
+	var height = imageHeight * .15;
+	var top = imageHeight - fontSize * 3.5 - height;
+	var textLeft = left + width + fontSize / 2;
+
+	var text = '';
+	
+	text += svgText(hueDisplayName, left, imageHeight - fontSize * 1.5);
+	
+	var svgtest = '<linearGradient id="gradient" x1="0%" y1="100%" x2="0%" y2="0%">';
+	
+	for ( var i = 0; i < hueStopPositions.length; i++ )
+	{
+		svgtest +=
+			'<stop offset="' + round(hueStopPositions[i] * 100) +
+			'%" style="stop-color:' + hueStopHsl[i] + '"/>';
+		
+		var textY = top + (1 - hueStopPositions[i]) * height;
+		
+		if
+		(
+			i == 0 ||
+			i == hueStopPositions.length - 1 ||
+			textY > top + fontSize && textY < top + height - fontSize
+		)
+		{
+			text += svgText(hueStopText[i], textLeft, textY);
+		}
+	}
+	
+	svgtest += '</linearGradient>';
+	//alert(svgtest);
+	svg += svgtest;
+	svg +=
+		'<rect style="fill:url(#gradient)" x="' + left + '" y="' + top +
+		'" width="' + width + '" height="' + height + '"/>';
+	
+	svg += text;
+}
+
+function drawSearchHighlights(label, bubbleX, bubbleY, rotation, center)
+{
+	var index = -1;
+	var labelLength = label.length;
+	
+	bubbleX -= fontSize / 4;
+	
+	do
+	{
+		index = label.toLowerCase().indexOf(search.value.toLowerCase(), index + 1);
+		
+		if ( index != -1 && index < labelLength )
+		{
+			var dim = context.measureText(label.substr(0, index));
+			var x = bubbleX + dim.width;
+			
+			dim = context.measureText(label.substr(index, search.value.length));
+			
+			var y = bubbleY - fontSize * 3 / 4;
+			var width = dim.width + fontSize / 2;
+			var height = fontSize * 3 / 2;
+			var radius = fontSize / 2;
+			
+			if ( snapshotMode )
+			{
+				if ( center )
+				{
+					x += centerX;
+					y += centerY;
+				}
+				
+				svg +=
+					'<rect x="' + x + '" y="' + y +
+					'" width="' + width +
+					'" height="' + height +
+					'" rx="' + radius +
+					'" ry="' + radius +
+					'" class="searchHighlight' +
+					'" transform="rotate(' +
+					degrees(rotation) + ',' + centerX + ',' + centerY +
+					')"/>';
+			}
+			else
+			{
+				context.fillStyle = 'rgb(255, 255, 100)';
+				context.rotate(rotation);
+				roundedRectangle(x, y, width, height, radius);
+				context.fill();
+				context.rotate(-rotation);
+			}
+		}
+	}
+	while ( index != -1 && index < labelLength );
+}
+
+function drawText(text, x, y, angle, anchor, bold, color)
+{
+	if ( color == undefined )
+	{
+		color = 'black';
+	}
+	
+	if ( snapshotMode )
+	{
+		svg +=
+			'<text x="' + (centerX + x) + '" y="' + (centerY + y) +
+			'" text-anchor="' + anchor + '" style="font-color:' + color + ';font-weight:' + (bold ? 'bold' : 'normal') +
+			'" transform="rotate(' + degrees(angle) + ',' + centerX + ',' + centerY + ')">' +
+			text + '</text>';
+	}
+	else
+	{
+		context.fillStyle = color;
+		context.textAlign = anchor;
+		context.font = bold ? fontBold : fontNormal;
+		context.rotate(angle);
+		context.fillText(text, x, y);
+		context.rotate(-angle);
+	}
+}
+
+function drawTextPolar
+(
+	text,
+	innerText,
+	angle,
+	radius,
+	radial,
+	bubble,
+	bold, 
+	searchResult,
+	searchResults
+)
+{
+	var anchor;
+	var textX;
+	var textY;
+	var spacer;
+	var totalText = text;
+	var flip;
+	
+	if ( snapshotMode )
+	{
+		spacer = '   ';
+	}
+	else
+	{
+		spacer = '   ';
+	}
+	
+	if ( radial )
+	{
+		flip = angle < 3 * Math.PI / 2;
+		
+		if ( flip )
+		{
+			angle -= Math.PI;
+			radius = -radius;
+			anchor = 'end';
+			
+			if ( innerText )
+			{
+				totalText = text + spacer + innerText;
+			}
+		}
+		else
+		{
+			anchor = 'start';
+			
+			if ( innerText )
+			{
+				totalText = innerText + spacer + text;
+			}
+		}
+		
+		textX = radius;
+		textY = 0;
+	}
+	else
+	{
+		flip = angle < Math.PI || angle > 2 * Math.PI;
+		var label;
+		
+		anchor = snapshotMode ? 'middle' : 'center';
+		
+		if ( flip )
+		{
+			angle -= Math.PI;
+			radius = -radius;
+		}
+		
+		angle += Math.PI / 2;
+		textX = 0;
+		textY = -radius;
+	}
+	
+	if ( bubble )
+	{
+		var textActual = totalText;
+		
+		if ( innerText && snapshotMode )
+		{
+			if ( flip )
+			{
+				textActual = text + '   ' + innerText;
+			}
+			else
+			{
+				textActual = innerText + '   ' + text;
+			}
+		}
+		
+		if ( searchResults )
+		{
+			textActual = textActual + searchResultString(searchResults);
+		}
+		
+		var textWidth = measureText(textActual, bold);
+		
+		var x = textX;
+		
+		if ( anchor == 'end' )
+		{
+			x -= textWidth;
+		}
+		else if ( anchor != 'start' )
+		{
+			// centered
+			x -= textWidth / 2;
+		}
+		
+		drawBubble(angle, radius, textWidth, radial, flip);
+		
+		if ( searchResult )
+		{
+			drawSearchHighlights
+			(
+				textActual,
+				x,
+				textY,
+				angle,
+				true
+			)
+		}
+	}
+	
+	if ( searchResults )
+	{
+		totalText = totalText + searchResultString(searchResults);
+	}
+	
+	drawText(totalText, textX, textY, angle, anchor, bold);
+	
+	return flip;
+}
+
+function drawTick(start, length, angle)
+{
+	if ( snapshotMode )
+	{
+		svg +=
+			'<line x1="' + (centerX + start) +
+			'" y1="' + centerY +
+			'" x2="' + (centerX + start + length) +
+			'" y2="' + centerY +
+			'" class="tick" transform="rotate(' +
+			degrees(angle) + ',' + centerX + ',' + centerY +
+			')"/>';
+	}
+	else
+	{
+		context.rotate(angle);
+		context.beginPath();
+		context.moveTo(start, 0);
+		context.lineTo(start + length, 0);
+		context.lineWidth = thinLineWidth * 2;
+		context.stroke();
+		context.rotate(-angle);
+	}
+}
+
+function drawWedge
+(
+	angleStart,
+	angleEnd,
+	radiusInner,
+	radiusOuter,
+	color,
+	patternAlpha,
+	highlight
+)
+{
+	if ( context.globalAlpha == 0 )
+	{
+		return;
+	}
+	
+	if ( snapshotMode )
+	{
+		if ( angleEnd == angleStart + Math.PI * 2 )
+		{
+			// fudge to prevent overlap, which causes arc ambiguity
+			//
+			angleEnd -= .1 / gRadius;
+		}
+		
+		var longArc = angleEnd - angleStart > Math.PI ? 1 : 0;
+		
+		var x1 = centerX + radiusInner * Math.cos(angleStart);
+		var y1 = centerY + radiusInner * Math.sin(angleStart);
+		
+		var x2 = centerX + gRadius * Math.cos(angleStart);
+		var y2 = centerY + gRadius * Math.sin(angleStart);
+		
+		var x3 = centerX + gRadius * Math.cos(angleEnd);
+		var y3 = centerY + gRadius * Math.sin(angleEnd);
+		
+		var x4 = centerX + radiusInner * Math.cos(angleEnd);
+		var y4 = centerY + radiusInner * Math.sin(angleEnd);
+		
+		var dArray =
+		[
+			" M ", x1, ",", y1,
+			" L ", x2, ",", y2,
+			" A ", gRadius, ",", gRadius, " 0 ", longArc, ",1 ", x3, ",", y3,
+			" L ", x4, ",", y4,
+			" A ", radiusInner, ",", radiusInner, " 0 ", longArc, " 0 ", x1, ",", y1,
+			" Z "
+		];
+		
+		svg +=
+			'<path class="'+ (highlight ? 'highlight' : 'wedge') + '" fill="' + color +
+			'" d="' + dArray.join('') + '"/>';
+		
+		if ( patternAlpha > 0 )
+		{
+			svg +=
+				'<path class="wedge" fill="url(#hiddenPattern)" d="' +
+				dArray.join('') + '"/>';
+		}
+	}
+	else
+	{
+		// fudge to prevent seams during animation
+		//
+		angleEnd += 1 / gRadius;
+		
+		context.fillStyle = color;
+		context.beginPath();
+		context.arc(0, 0, radiusInner, angleStart, angleEnd, false);
+		context.arc(0, 0, radiusOuter, angleEnd, angleStart, true);
+		context.closePath();
+		context.fill();
+		
+		if ( patternAlpha > 0 )
+		{
+			context.save();
+			context.clip();
+			context.globalAlpha = patternAlpha;
+			context.fillStyle = hiddenPattern;
+			context.fill();
+			context.restore();
+		}
+		
+		if ( highlight )
+		{
+			context.lineWidth = highlight ? highlightLineWidth : thinLineWidth;
+			context.strokeStyle = 'black';
+			context.stroke();
+		}
+	}
+}
+
+function expand(node)
+{
+	selectNode(node);
+	updateView();
+}
+
+function focusLost()
+{
+	mouseX = -1;
+	mouseY = -1;
+	checkHighlight();
+	document.body.style.cursor = 'auto';
+}
+
+function fontSizeDecrease()
+{
+	if ( fontSize > 1 )
+	{
+		fontSize--;
+		updateViewNeeded = true;
+	}
+}
+
+function fontSizeIncrease()
+{
+	fontSize++;
+	updateViewNeeded = true;
+}
+
+function getGetString(name, value, bool)
+{
+	return name + '=' + (bool ? value ? 'true' : 'false' : value);
+}
+
+function hideLink()
+{
+	hide(linkText);
+	show(linkButton);
+}
+
+function show(object)
+{
+	object.style.display = 'inline';
+}
+
+function hide(object)
+{
+	object.style.display = 'none';
+}
+
+function showLink()
+{
+	var urlHalves = String(document.location).split('?');
+	var newGetVariables = new Array();
+	
+	newGetVariables.push
+	(
+		getGetString('dataset', currentDataset, false),
+		getGetString('node', selectedNode.id, false),
+		getGetString('collapse', collapse, true),
+		getGetString('color', useHue(), true),
+		getGetString('depth', maxAbsoluteDepth - 1, false),
+		getGetString('font', fontSize, false),
+		getGetString('key', showKeys, true)
+	);
+	
+	hide(linkButton);
+	show(linkText);
+	linkText.value = urlHalves[0] + '?' + getVariables.concat(newGetVariables).join('&');
+	//linkText.disabled = false;
+	linkText.focus();
+	linkText.select();
+	//linkText.disabled = true;
+//	document.location = urlHalves[0] + '?' + getVariables.join('&');
+}
+
+function getFirstChild(element)
+{
+	element = element.firstChild;
+	
+	if ( element && element.nodeType != 1 )
+	{
+		element = getNextSibling(element);
+	}
+	
+	return element;
+}
+
+function getNextSibling(element)
+{
+	do
+	{
+		element = element.nextSibling;
+	}
+	while ( element && element.nodeType != 1 );
+	
+	return element;
+}
+
+function getPercentage(fraction)
+{
+	return round(fraction * 100);
+}
+
+function hslText(hue)
+{
+	if ( 1 || snapshotMode )
+	{
+		// Safari doesn't seem to allow hsl() in SVG
+		
+		var rgb = hslToRgb(hue, saturation, (lightnessBase + lightnessMax) / 2);
+		
+		return rgbText(rgb.r, rgb.g, rgb.b);
+	}
+	else
+	{
+		var hslArray =
+		[
+			'hsl(',
+			Math.floor(hue * 360),
+			',',
+			Math.floor(saturation * 100),
+			'%,',
+			Math.floor((lightnessBase + lightnessMax) * 50),
+			'%)'
+		];
+		
+		return hslArray.join('');
+	}
+}
+
+function hslToRgb(h, s, l)
+{
+	var m1, m2;
+	var r, g, b;
+	
+	if (s == 0)
+	{
+		r = g = b = Math.floor((l * 255));
+	}
+	else
+	{
+		if (l <= 0.5)
+		{
+			m2 = l * (s + 1);
+		}
+		else
+		{
+			m2 = l + s - l * s;
+		}
+		
+		m1 = l * 2 - m2;
+		
+		r = Math.floor(hueToRgb(m1, m2, h + 1 / 3));
+		g = Math.floor(hueToRgb(m1, m2, h));
+		b = Math.floor(hueToRgb(m1, m2, h - 1/3));
+	}
+	
+	return {r: r, g: g, b: b};
+}
+
+function hueToRgb(m1, m2, hue)
+{
+	var v;
+	
+	while (hue < 0)
+	{
+		hue += 1;
+	}
+	
+	while (hue > 1)
+	{
+		hue -= 1;
+	}
+	
+	if (6 * hue < 1)
+		v = m1 + (m2 - m1) * hue * 6;
+	else if (2 * hue < 1)
+		v = m2;
+	else if (3 * hue < 2)
+		v = m1 + (m2 - m1) * (2/3 - hue) * 6;
+	else
+		v = m1;
+
+	return 255 * v;
+}
+
+function interpolateHue(hueStart, hueEnd, valueStart, valueEnd)
+{
+	// since the gradient will be RGB based, we need to add stops to hit all the
+	// colors in the hue spectrum
+	
+	hueStopPositions = new Array();
+	hueStopHsl = new Array();
+	hueStopText = new Array();
+	
+	hueStopPositions.push(0);
+	hueStopHsl.push(hslText(hueStart));
+	hueStopText.push(round(valueStart));
+	
+	for
+	(
+		var i = (hueStart > hueEnd ? 5 / 6 : 1 / 6);
+		(hueStart > hueEnd ? i > 0 : i < 1);
+		i += (hueStart > hueEnd ? -1 : 1) / 6
+	)
+	{
+		if
+		(
+			hueStart > hueEnd ?
+				i > hueEnd && i < hueStart :
+				i > hueStart && i < hueEnd
+		)
+		{
+			hueStopPositions.push(lerp(i, hueStart, hueEnd, 0, 1));
+			hueStopHsl.push(hslText(i));
+			hueStopText.push(round(lerp
+			(
+				i,
+				hueStart,
+				hueEnd,
+				valueStart,
+				valueEnd
+			)));
+		}
+	}
+	
+	hueStopPositions.push(1);
+	hueStopHsl.push(hslText(hueEnd));
+	hueStopText.push(round(valueEnd));
+}
+
+function keyLineAngle(angle, keyAngle, bendRadius, keyX, keyY, pointsX, pointsY)
+{
+	if ( angle < Math.PI / 2 && keyY < bendRadius * Math.sin(angle) 
+	|| angle > Math.PI / 2 && keyY < bendRadius)
+	{
+		return Math.asin(keyY / bendRadius);
+	}
+	else
+	{
+		// find the angle of the normal to a tangent line that goes to
+		// the label
+		
+		var textDist = Math.sqrt
+		(
+			Math.pow(keyX, 2) +
+			Math.pow(keyY, 2)
+		);
+		
+		var tanAngle = Math.acos(bendRadius / textDist) + keyAngle;
+		
+		if ( angle < tanAngle || angle < Math.PI / 2 )//|| labelLeft < centerX )
+		{
+			// angle doesn't reach far enough for tangent; collapse and
+			// connect directly to label
+			
+			if ( keyY / Math.tan(angle) > 0 )
+			{
+				pointsX.push(keyY / Math.tan(angle));
+				pointsY.push(keyY);
+			}
+			else
+			{
+				pointsX.push(bendRadius * Math.cos(angle));
+				pointsY.push(bendRadius * Math.sin(angle));
+			}
+			
+			return angle;
+		}
+		else
+		{
+			return tanAngle;
+		}
+	}
+}
+
+function keyOffset()
+{
+	return imageHeight - (keys - currentKey + 1) * (keySize + keyBuffer) + keyBuffer - margin;
+}
+
+function lerp(value, fromStart, fromEnd, toStart, toEnd)
+{
+	return (value - fromStart) *
+		(toEnd - toStart) /
+		(fromEnd - fromStart) +
+		toStart;
+}
+
+function createCanvas()
+{
+	canvas = document.createElement('canvas');
+	document.body.appendChild(canvas);
+	context = canvas.getContext('2d');
+}
+
+function load()
+{
+	document.body.style.overflow = "hidden";
+	document.body.style.margin = 0;
+	
+	createCanvas();
+	
+	if ( context == undefined )
+	{
+		document.body.innerHTML = '\
+<br/>This browser does not support HTML5 (see \
+<a href="https://github.com/marbl/Krona/wiki/Browser%20support">Browser support</a>).\
+	';
+		return;
+	}
+
+	if ( typeof context.fillText != 'function' )
+	{
+		document.body.innerHTML = '\
+<br/>This browser does not support HTML5 canvas text (see \
+<a href="https://github.com/marbl/Krona/wiki/Browser%20support">Browser support</a>).\
+	';
+		return;
+	}
+	
+	resize();
+	
+	var kronaElement = document.getElementsByTagName('krona')[0];
+	
+	var magnitudeName;
+	var hueName;
+	var hueDefault;
+	var hueStart;
+	var hueEnd;
+	var valueStart;
+	var valueEnd;
+	
+	if ( kronaElement.getAttribute('collapse') != undefined )
+	{
+		collapse = kronaElement.getAttribute('collapse') == 'true';
+	}
+	
+	if ( kronaElement.getAttribute('key') != undefined )
+	{
+		showKeys = kronaElement.getAttribute('key') == 'true';
+	}
+	
+	for
+	(
+		var element = getFirstChild(kronaElement);
+		element;
+		element = getNextSibling(element)
+	)
+	{
+		switch ( element.tagName.toLowerCase() )
+		{
+			case 'attributes':
+				magnitudeName = element.getAttribute('magnitude');
+				//
+				for
+				(
+					var attributeElement = getFirstChild(element);
+					attributeElement;
+					attributeElement = getNextSibling(attributeElement)
+				)
+				{
+					var tag = attributeElement.tagName.toLowerCase();
+					
+					if ( tag == 'attribute' )
+					{
+						var attribute = new Attribute();
+						attribute.name = attributeElement.firstChild.nodeValue.toLowerCase();
+						attribute.displayName = attributeElement.getAttribute('display');
+						
+						if ( attributeElement.getAttribute('hrefBase') )
+						{
+							attribute.hrefBase = attributeElement.getAttribute('hrefBase');
+						}
+						
+						if ( attributeElement.getAttribute('target') )
+						{
+							attribute.target = attributeElement.getAttribute('target');
+						}
+						
+						if ( attribute.name == magnitudeName )
+						{
+							magnitudeIndex = attributes.length;
+						}
+						
+						if ( attributeElement.getAttribute('listAll') )
+						{
+							attribute.listAll = attributeElement.getAttribute('listAll').toLowerCase();
+						}
+						else if ( attributeElement.getAttribute('listNode') )
+						{
+							attribute.listNode = attributeElement.getAttribute('listNode').toLowerCase();
+						}
+						else if ( attributeElement.getAttribute('dataAll') )
+						{
+							attribute.dataAll = attributeElement.getAttribute('dataAll').toLowerCase();
+						}
+						else if ( attributeElement.getAttribute('dataNode') )
+						{
+							attribute.dataNode = attributeElement.getAttribute('dataNode').toLowerCase();
+						}
+						
+						if ( attributeElement.getAttribute('postUrl') )
+						{
+							attribute.postUrl = attributeElement.getAttribute('postUrl');
+						}
+						
+						if ( attributeElement.getAttribute('postVar') )
+						{
+							attribute.postVar = attributeElement.getAttribute('postVar');
+						}
+						
+						if ( attributeElement.getAttribute('mono') )
+						{
+							attribute.mono = true;
+						}
+						
+						attributes.push(attribute);
+					}
+					else if ( tag == 'list' )
+					{
+						var attribute = new Attribute();
+						
+						attribute.name = attributeElement.firstChild.nodeValue;
+						attribute.list = true;
+						attributes.push(attribute);
+					}
+					else if ( tag == 'data' )
+					{
+						var attribute = new Attribute();
+						
+						attribute.name = attributeElement.firstChild.nodeValue;
+						attribute.data = true;
+						attributes.push(attribute);
+						
+						var enableScript = document.createElement('script');
+						var date = new Date();
+						enableScript.src =
+							attributeElement.getAttribute('enable') + '?' +
+							date.getTime();
+						document.body.appendChild(enableScript);
+					}
+				}
+				break;
+			
+			case 'color':
+				hueName = element.getAttribute('attribute');
+				hueStart = Number(element.getAttribute('hueStart')) / 360;
+				hueEnd = Number(element.getAttribute('hueEnd')) / 360;
+				valueStart = Number(element.getAttribute('valueStart'));
+				valueEnd = Number(element.getAttribute('valueEnd'));
+				//
+				interpolateHue(hueStart, hueEnd, valueStart, valueEnd);
+				//
+				if ( element.getAttribute('default') == 'true' )
+				{
+					hueDefault = true;
+				}
+				break;
+			
+			case 'datasets':
+				datasetNames = new Array();
+				//
+				for ( j = getFirstChild(element); j; j = getNextSibling(j) )
+				{
+					datasetNames.push(j.firstChild.nodeValue);
+				}
+				datasets = datasetNames.length;
+				break;
+			
+			case 'node':
+				head = loadTreeDOM
+				(
+					element,
+					magnitudeName,
+					hueName,
+					hueStart,
+					hueEnd,
+					valueStart,
+					valueEnd
+				);
+				break;
+		}
+	}
+	
+	// get GET options
+	//
+	var urlHalves = String(document.location).split('?');
+	var datasetDefault = 0;
+	var maxDepthDefault;
+	var nodeDefault = 0;
+	//
+	if ( urlHalves[1] )
+	{
+		var vars = urlHalves[1].split('&');
+		
+		for ( i = 0; i < vars.length; i++ )
+		{
+			var pair = vars[i].split('=');
+			
+			switch ( pair[0] )
+			{
+				case 'collapse':
+					collapse = pair[1] == 'true';
+					break;
+				
+				case 'color':
+					hueDefault = pair[1] == 'true';
+					break;
+				
+				case 'dataset':
+					datasetDefault = Number(pair[1]);
+					break;
+					
+				case 'depth':
+					maxDepthDefault = Number(pair[1]) + 1;
+					break;
+				
+				case 'key':
+					showKeys = pair[1] == 'true';
+					break;
+				
+				case 'font':
+					fontSize = Number(pair[1]);
+					break;
+				
+				case 'node':
+					nodeDefault = Number(pair[1]);
+					break;
+				
+				default:
+					getVariables.push(pair[0] + '=' + pair[1]);
+					break;
+			}
+		}
+	}
+	
+	addOptionElements(hueName, hueDefault);
+	setCallBacks();
+	
+	head.sort();
+	maxAbsoluteDepth = 0;
+	selectDataset(datasetDefault);
+	
+	if ( maxDepthDefault && maxDepthDefault < head.maxDepth )
+	{
+		maxAbsoluteDepth = maxDepthDefault;
+	}
+	else
+	{
+		maxAbsoluteDepth = head.maxDepth;
+	}
+	
+	selectNode(nodes[nodeDefault]);
+	
+	setInterval(update, 20);
+	
+	window.onresize = handleResize;
+	updateMaxAbsoluteDepth();
+	updateViewNeeded = true;
+}
+
+function loadTreeDOM
+(
+	domNode,
+	magnitudeName,
+	hueName,
+	hueStart,
+	hueEnd,
+	valueStart,
+	valueEnd
+)
+{
+	var newNode = new Node();
+	
+	newNode.name = domNode.getAttribute('name');
+	
+	if ( domNode.getAttribute('href') )
+	{
+		newNode.href = domNode.getAttribute('href');
+	}
+	
+	if ( hueName )
+	{
+		newNode.hues = new Array();
+	}
+	
+	for ( var i = getFirstChild(domNode); i; i = getNextSibling(i) )
+	{
+		switch ( i.tagName.toLowerCase() )
+		{
+		case 'node': 
+			var newChild = loadTreeDOM
+			(
+				i,
+				magnitudeName,
+				hueName,
+				hueStart,
+				hueEnd,
+				valueStart,
+				valueEnd
+			);
+			newChild.parent = newNode;
+			newNode.children.push(newChild);
+			break;
+			
+		default:
+			var attributeName = i.tagName.toLowerCase();
+			var index = attributeIndex(attributeName);
+			//
+			newNode.attributes[index] = new Array();
+			//
+			for ( var j = getFirstChild(i); j; j = getNextSibling(j) )
+			{
+				if ( attributes[index] == undefined )
+				{
+					var x = 5;
+				}
+				if ( attributes[index].list )
+				{
+					newNode.attributes[index].push(new Array());
+					
+					for ( var k = getFirstChild(j); k; k = getNextSibling(k) )
+					{
+						newNode.attributes[index][newNode.attributes[index].length - 1].push(k.firstChild.nodeValue);
+					}
+				}
+				else
+				{
+					var value = j.firstChild ? j.firstChild.nodeValue : '';
+					
+					if ( j.getAttribute('href') )
+					{
+						var target;
+						
+						if ( attributes[index].target )
+						{
+							target = ' target="' + attributes[index].target + '"';
+						}
+						
+						value = '<a href="' + attributes[index].hrefBase + j.getAttribute('href') + '"' + target + '>' + value + '</a>';
+					}
+					
+					newNode.attributes[index].push(value);
+				}
+			}
+			//
+			if ( attributeName == magnitudeName || attributeName == hueName )
+			{
+				for ( j = 0; j < datasets; j++ )
+				{
+					var value = newNode.attributes[index][j] == undefined ? 0 : Number(newNode.attributes[index][j]);
+					
+					newNode.attributes[index][j] = value;
+					
+					if ( attributeName == hueName )
+					{
+						var hue = lerp
+						(
+							value,
+							valueStart,
+							valueEnd,
+							hueStart,
+							hueEnd
+						);
+						
+						if ( hue < hueStart == hueStart < hueEnd )
+						{
+							hue = hueStart;
+						}
+						else if ( hue > hueEnd == hueStart < hueEnd )
+						{
+							hue = hueEnd;
+						}
+						
+						newNode.hues[j] = hue;
+					}
+				}
+				
+				if ( attributeName == hueName )
+				{
+					newNode.hue = new Tween(newNode.hues[0], newNode.hues[0]);
+				}
+			}
+			break;
+		}
+	}
+	
+	return newNode;
+}
+
+function maxAbsoluteDepthDecrease()
+{
+	if ( maxAbsoluteDepth > 2 )
+	{
+		maxAbsoluteDepth--;
+		head.setMaxDepths();
+		handleResize();
+	}
+}
+
+function maxAbsoluteDepthIncrease()
+{
+	if ( maxAbsoluteDepth < head.maxDepth )
+	{
+		maxAbsoluteDepth++;
+		head.setMaxDepths();
+		handleResize();
+	}
+}
+
+function measureText(text, bold)
+{
+	context.font = bold ? fontBold : fontNormal;
+	var dim = context.measureText(text);
+	return dim.width;
+}
+
+function min(a, b)
+{
+	return a < b ? a : b;
+}
+
+function minWidth()
+{
+	// Min wedge width (at center) for displaying a node (or for displaying a
+	// label if it's at the highest level being viewed, multiplied by 2 to make
+	// further calculations simpler
+	
+	return (fontSize * 2.3);
+}
+
+function mouseMove(e)
+{
+	mouseX = e.pageX;
+	mouseY = e.pageY - headerHeight;
+	mouseXRel = (mouseX - centerX) * backingScale()
+	mouseYRel = (mouseY - centerY) * backingScale()
+	
+	if ( head && ! quickLook )
+	{
+		checkHighlight();
+	}
+}
+
+function mouseClick(e)
+{
+	if ( highlightedNode == focusNode && focusNode != selectedNode || selectedNode.hasParent(highlightedNode) )
+	{
+		if ( highlightedNode.hasChildren() )
+		{
+			expand(highlightedNode);
+		}
+	}
+	else if ( progress == 1 )//( highlightedNode != selectedNode )
+	{
+		setFocus(highlightedNode);
+//		document.body.style.cursor='ew-resize';
+		draw();
+		checkHighlight();
+		var date = new Date();
+		mouseDownTime = date.getTime();
+		mouseDown = true;
+	}
+}
+
+function mouseUp(e)
+{
+	if ( quickLook )
+	{
+		navigateBack();
+		quickLook = false;
+	}
+	
+	mouseDown = false;
+}
+
+function navigateBack()
+{
+	if ( nodeHistoryPosition > 0 )
+	{
+		nodeHistory[nodeHistoryPosition] = selectedNode;
+		nodeHistoryPosition--;
+		
+		if ( nodeHistory[nodeHistoryPosition].collapse )
+		{
+			collapseCheckBox.checked = collapse = false;
+		}
+		
+		setSelectedNode(nodeHistory[nodeHistoryPosition]);
+		updateDatasetButtons();
+		updateView();
+	}
+}
+
+function navigateUp()
+{
+	if ( selectedNode.getParent() )
+	{
+		selectNode(selectedNode.getParent());
+		updateView();
+	}
+}
+
+function navigateForward()
+{
+	if ( nodeHistoryPosition < nodeHistory.length - 1 )
+	{
+		nodeHistoryPosition++;
+		var newNode = nodeHistory[nodeHistoryPosition];
+		
+		if ( newNode.collapse )
+		{
+			collapseCheckBox.checked = collapse = false;
+		}
+		
+		if ( nodeHistoryPosition == nodeHistory.length - 1 )
+		{
+			// this will ensure the forward button is disabled
+			
+			nodeHistory.length = nodeHistoryPosition;
+		}
+		
+		setSelectedNode(newNode);
+		updateDatasetButtons();
+		updateView();
+	}
+}
+
+function nextDataset()
+{
+	var newDataset = currentDataset;
+	
+	do
+	{
+		if ( newDataset == datasets - 1 )
+		{
+			newDataset = 0;
+		}
+		else
+		{
+			newDataset++;
+		}
+	}
+	while ( datasetDropDown.options[newDataset].disabled )
+	
+	selectDataset(newDataset);
+}
+
+function onDatasetChange()
+{
+	selectDataset(datasetDropDown.selectedIndex);
+}
+
+function onKeyDown(event)
+{
+	if
+	(
+		event.keyCode == 37 &&
+		document.activeElement.id != 'search' &&
+		document.activeElement.id != 'linkText'
+	)
+	{
+		navigateBack();
+		event.preventDefault();
+	}
+	else if
+	(
+		event.keyCode == 39 &&
+		document.activeElement.id != 'search' &&
+		document.activeElement.id != 'linkText'
+	)
+	{
+		navigateForward();
+		event.preventDefault();
+	}
+	else if ( event.keyCode == 38 && datasets > 1 )
+	{
+		prevDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+	else if ( event.keyCode == 40 && datasets > 1 )
+	{
+		nextDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+	else if ( event.keyCode == 9 && datasets > 1 )
+	{
+		selectLastDataset();
+		event.preventDefault();
+	}
+	else if ( event.keyCode == 83 )
+	{
+		progress += .2;
+	}
+	else if ( event.keyCode == 66 )
+	{
+		progress -= .2;
+	}
+	else if ( event.keyCode == 70 )
+	{
+		progress = 1;
+	}
+}
+
+function onKeyPress(event)
+{
+	if ( event.keyCode == 38 && datasets > 1 )
+	{
+//		prevDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+	else if ( event.keyCode == 40 && datasets > 1 )
+	{
+//		nextDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+}
+
+function onKeyUp(event)
+{
+	if ( event.keyCode == 27 && document.activeElement.id == 'search' )
+	{
+		search.value = '';
+		onSearchChange();
+	}
+	else if ( event.keyCode == 38 && datasets > 1 )
+	{
+//		prevDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+	else if ( event.keyCode == 40 && datasets > 1 )
+	{
+//		nextDataset();
+		
+		//if ( document.activeElement.id == 'datasets' )
+		{
+			event.preventDefault();
+		}
+	}
+}
+
+function onSearchChange()
+{
+	nSearchResults = 0;
+	head.search();
+	
+	if ( search.value == '' )
+	{
+		searchResults.innerHTML = '';
+	}
+	else
+	{
+		searchResults.innerHTML = nSearchResults + ' results';
+	}
+	
+	setFocus(selectedNode);
+	draw();
+}
+
+function post(url, variable, value, postWindow)
+{
+	var form = document.createElement('form');
+	var input = document.createElement('input');
+	var inputDataset = document.createElement('input');
+	
+	form.appendChild(input);
+	form.appendChild(inputDataset);
+	
+	form.method = "POST";
+	form.action = url;
+	
+	if ( postWindow == undefined )
+	{
+		form.target = '_blank';
+		postWindow = window;
+	}
+	
+	input.type = 'hidden';
+	input.name = variable;
+	input.value = value;
+	
+	inputDataset.type = 'hidden';
+	inputDataset.name = 'dataset';
+	inputDataset.value = currentDataset;
+	
+	postWindow.document.body.appendChild(form);
+	form.submit();
+}
+
+function prevDataset()
+{
+	var newDataset = currentDataset;
+	
+	do
+	{
+		if ( newDataset == 0 )
+		{
+			newDataset = datasets - 1;
+		}
+		else
+		{
+			newDataset--;
+		}
+	}
+	while ( datasetDropDown.options[newDataset].disabled );
+	
+	selectDataset(newDataset);
+}
+
+function radiusDecrease()
+{
+	if ( bufferFactor < .309 )
+	{
+		bufferFactor += .03;
+		updateViewNeeded = true;
+	}
+}
+
+function radiusIncrease()
+{
+	if ( bufferFactor > .041 )
+	{
+		bufferFactor -= .03;
+		updateViewNeeded = true;
+	}
+}
+
+function resetKeyOffset()
+{
+	currentKey = 1;
+	keyMinTextLeft = centerX + gRadius + buffer - buffer / (keys + 1) / 2 + fontSize / 2;
+	keyMinAngle = 0;
+}
+
+function rgbText(r, g, b)
+{
+	var rgbArray =
+	[
+		"rgb(",
+		Math.floor(r),
+		",",
+		Math.floor(g),
+		",",
+		Math.floor(b),
+		")"
+	];
+	
+	return rgbArray.join('');
+}
+
+function round(number)
+{
+	if ( number >= 1 || number <= -1 )
+	{
+		return number.toFixed(0);
+	}
+	else
+	{
+		return number.toPrecision(1);
+	}
+}
+
+function roundedRectangle(x, y, width, height, radius)
+{
+	if ( radius * 2 > width )
+	{
+		radius = width / 2;
+	}
+	
+	if ( radius * 2 > height )
+	{
+		radius = height / 2;
+	}
+	
+	context.beginPath();
+	context.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2, false);
+	context.lineTo(x + width - radius, y);
+	context.arc(x + width - radius, y + radius, radius, Math.PI * 3 / 2, Math.PI * 2, false);
+	context.lineTo(x + width, y + height - radius);
+	context.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2, false);
+	context.lineTo(x + radius, y + height);
+	context.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI, false);
+	context.lineTo(x, y + radius);
+}
+
+function passClick(e)
+{
+	mouseClick(e);
+}
+
+function searchResultString(results)
+{
+	var searchResults = this.searchResults;
+	
+	if ( this.isSearchResult )
+	{
+		// don't count ourselves
+		searchResults--;
+	}
+	
+	return ' - ' + results + (results > 1 ? ' results' : ' result');
+}
+
+function setCallBacks()
+{
+	canvas.onselectstart = function(){return false;} // prevent unwanted highlighting
+	options.onselectstart = function(){return false;} // prevent unwanted highlighting
+	document.onmousemove = mouseMove;
+	window.onblur = focusLost;
+	window.onmouseout = focusLost;
+	document.onkeyup = onKeyUp;
+	document.onkeydown = onKeyDown;
+	canvas.onmousedown = mouseClick;
+	document.onmouseup = mouseUp;
+	keyControl.onclick = toggleKeys;
+	collapseCheckBox = document.getElementById('collapse');
+	collapseCheckBox.checked = collapse;
+	collapseCheckBox.onclick = handleResize;
+	collapseCheckBox.onmousedown = suppressEvent;
+	maxAbsoluteDepthText = document.getElementById('maxAbsoluteDepth');
+	maxAbsoluteDepthButtonDecrease = document.getElementById('maxAbsoluteDepthDecrease');
+	maxAbsoluteDepthButtonIncrease = document.getElementById('maxAbsoluteDepthIncrease');
+	maxAbsoluteDepthButtonDecrease.onclick = maxAbsoluteDepthDecrease;
+	maxAbsoluteDepthButtonIncrease.onclick = maxAbsoluteDepthIncrease;
+	maxAbsoluteDepthButtonDecrease.onmousedown = suppressEvent;
+	maxAbsoluteDepthButtonIncrease.onmousedown = suppressEvent;
+	fontSizeText = document.getElementById('fontSize');
+	fontSizeButtonDecrease = document.getElementById('fontSizeDecrease');
+	fontSizeButtonIncrease = document.getElementById('fontSizeIncrease');
+	fontSizeButtonDecrease.onclick = fontSizeDecrease;
+	fontSizeButtonIncrease.onclick = fontSizeIncrease;
+	fontSizeButtonDecrease.onmousedown = suppressEvent;
+	fontSizeButtonIncrease.onmousedown = suppressEvent;
+	radiusButtonDecrease = document.getElementById('radiusDecrease');
+	radiusButtonIncrease = document.getElementById('radiusIncrease');
+	radiusButtonDecrease.onclick = radiusDecrease;
+	radiusButtonIncrease.onclick = radiusIncrease;
+	radiusButtonDecrease.onmousedown = suppressEvent;
+	radiusButtonIncrease.onmousedown = suppressEvent;
+	maxAbsoluteDepth = 0;
+	backButton = document.getElementById('back');
+	backButton.onclick = navigateBack;
+	backButton.onmousedown = suppressEvent;
+	forwardButton = document.getElementById('forward');
+	forwardButton.onclick = navigateForward;
+	forwardButton.onmousedown = suppressEvent;
+	snapshotButton = document.getElementById('snapshot');
+	snapshotButton.onclick = snapshot;
+	snapshotButton.onmousedown = suppressEvent;
+	detailsName = document.getElementById('detailsName');
+	detailsExpand = document.getElementById('detailsExpand');
+	detailsInfo = document.getElementById('detailsInfo');
+	search = document.getElementById('search');
+	search.onkeyup = onSearchChange;
+	search.onmousedown = suppressEvent;
+	searchResults = document.getElementById('searchResults');
+	useHueDiv = document.getElementById('useHueDiv');
+	linkButton = document.getElementById('linkButton');
+	linkButton.onclick = showLink;
+	linkButton.onmousedown = suppressEvent;
+	linkText = document.getElementById('linkText');
+	linkText.onblur = hideLink;
+	linkText.onmousedown = suppressEvent;
+	hide(linkText);
+	var helpButton = document.getElementById('help');
+	helpButton.onmousedown = suppressEvent;
+	var searchClear = document.getElementById('searchClear');
+	searchClear.onmousedown = suppressEvent;
+	if ( datasets > 1 )
+	{
+		datasetDropDown.onmousedown = suppressEvent;
+		var prevDatasetButton = document.getElementById('prevDataset');
+		prevDatasetButton.onmousedown = suppressEvent;
+		var nextDatasetButton = document.getElementById('nextDataset');
+		nextDatasetButton.onmousedown = suppressEvent;
+		var lastDatasetButton = document.getElementById('lastDataset');
+		lastDatasetButton.onmousedown = suppressEvent;
+	}
+	
+	image = document.getElementById('hiddenImage');
+	
+	if ( image.complete )
+	{
+		hiddenPattern = context.createPattern(image, 'repeat');
+	}
+	else
+	{
+		image.onload = function()
+		{
+			hiddenPattern = context.createPattern(image, 'repeat');
+		}
+	}
+	
+	var loadingImageElement = document.getElementById('loadingImage');
+	
+	if ( loadingImageElement )
+	{
+		loadingImage = loadingImageElement.src;
+	}
+}
+
+function selectDataset(newDataset)
+{
+	lastDataset = currentDataset;
+	currentDataset = newDataset
+	if ( datasets > 1 )
+	{
+		datasetDropDown.selectedIndex = currentDataset;
+		updateDatasetButtons();
+		datasetAlpha.start = 1.5;
+		datasetChanged = true;
+	}
+	head.setMagnitudes(0);
+	head.setDepth(1, 1);
+	head.setMaxDepths();
+	handleResize();
+}
+
+function selectLastDataset()
+{
+	selectDataset(lastDataset);
+	handleResize();
+}
+
+function selectNode(newNode)
+{
+	if ( selectedNode != newNode )
+	{
+		// truncate history at current location to create a new branch
+		//
+		nodeHistory.length = nodeHistoryPosition;
+		
+		if ( selectedNode != 0 )
+		{
+			nodeHistory.push(selectedNode);
+			nodeHistoryPosition++;
+		}
+		
+		setSelectedNode(newNode);
+		//updateView();
+	}
+	
+	updateDatasetButtons();
+}
+
+function setFocus(node)
+{
+	if ( node == focusNode )
+	{
+//		return;
+	}
+	
+	focusNode = node;
+	
+	if ( node.href )
+	{
+		detailsName.innerHTML =
+			'<a target="_blank" href="' + node.href + '">' + node.name + '</a>';
+	}
+	else
+	{
+		detailsName.innerHTML = node.name;
+	}
+	
+	var table = '<table>';
+	
+	table += '<tr><td></td></tr>';
+	
+	for ( var i = 0; i < node.attributes.length; i++ )
+	{
+		if ( attributes[i].displayName && node.attributes[i] != undefined )
+		{
+			var index = node.attributes[i].length == 1 && attributes[i].mono ? 0 : currentDataset;
+			
+			if ( typeof node.attributes[i][currentDataset] == 'number' || node.attributes[i][index] != undefined && node.attributes[i][currentDataset] != '' )
+			{
+				var value = node.attributes[i][index];
+				
+				if ( attributes[i].listNode != undefined )
+				{
+					value =
+						'<a href="" onclick="showList(' +
+						attributeIndex(attributes[i].listNode) + ',' + i +
+						',false);return false;" title="Show list">' +
+						value + '</a>';
+				}
+				else if ( attributes[i].listAll != undefined )
+				{
+					value =
+						'<a href="" onclick="showList(' +
+						attributeIndex(attributes[i].listAll) + ',' + i +
+						',true);return false;" title="Show list">' +
+						value + '</a>';
+				}
+				else if ( attributes[i].dataNode != undefined && dataEnabled )
+				{
+					value =
+						'<a href="" onclick="showData(' +
+						attributeIndex(attributes[i].dataNode) + ',' + i +
+						',false);return false;" title="Show data">' +
+						value + '</a>';
+				}
+				else if ( attributes[i].dataAll != undefined && dataEnabled )
+				{
+					value =
+						'<a href="" onclick="showData(' +
+						attributeIndex(attributes[i].dataAll) + ',' + i +
+						',true);return false;" title="Show data">' +
+						value + '</a>';
+				}
+				
+				table +=
+					'<tr><td><strong>' + attributes[i].displayName + ':</strong></td><td>' +
+					value + '</td></tr>';
+			}
+		}
+	}
+	
+	table += '</table>';
+	detailsInfo.innerHTML = table;
+	
+	detailsExpand.disabled = !focusNode.hasChildren() || focusNode == selectedNode;
+}
+
+function setSelectedNode(newNode)
+{
+	if ( selectedNode && selectedNode.hasParent(newNode) )
+	{
+		zoomOut = true;
+	}
+	else
+	{
+		zoomOut = false;
+	}
+	
+	selectedNodeLast = selectedNode;
+	selectedNode = newNode;
+	
+	//if ( focusNode != selectedNode )
+	{
+		setFocus(selectedNode);
+	}
+}
+
+function waitForData(dataWindow, target, title, time, postUrl, postVar)
+{
+	if ( nodeData.length == target )
+	{
+		if ( postUrl != undefined )
+		{
+			for ( var i = 0; i < nodeData.length; i++ )
+			{
+				nodeData[i] = nodeData[i].replace(/\n/g, ',');
+			}
+			
+			var postString = nodeData.join('');
+			postString = postString.slice(0, -1);
+			
+			dataWindow.document.body.removeChild(dataWindow.document.getElementById('loading'));
+			document.body.removeChild(document.getElementById('data'));
+			
+			post(postUrl, postVar, postString, dataWindow);
+		}
+		else
+		{
+			//dataWindow.document.body.removeChild(dataWindow.document.getElementById('loading'));
+			//document.body.removeChild(document.getElementById('data'));
+			
+			dataWindow.document.open();
+			dataWindow.document.write('<pre>' + nodeData.join('') + '</pre>');
+			dataWindow.document.close();
+		}
+		
+		dataWindow.document.title = title; // replace after document.write()
+	}
+	else
+	{
+		var date = new Date();
+		
+		if ( date.getTime() - time > 10000 )
+		{
+			dataWindow.document.body.removeChild(dataWindow.document.getElementById('loading'));
+			document.body.removeChild(document.getElementById('data'));
+			dataWindow.document.body.innerHTML =
+				'Timed out loading supplemental files for:<br/>' + document.location;
+		}
+		else
+		{
+			setTimeout(function() {waitForData(dataWindow, target, title, time, postUrl, postVar);}, 100);
+		}
+	}
+}
+
+function data(newData)
+{
+	nodeData.push(newData);
+}
+
+function enableData()
+{
+	dataEnabled = true;
+}
+
+function showData(indexData, indexAttribute, summary)
+{
+	var dataWindow = window.open('', '_blank');
+	var title = 'Krona - ' + attributes[indexAttribute].displayName + ' - ' + focusNode.name;
+	dataWindow.document.title = title;
+	
+	nodeData = new Array();
+	
+	if ( dataWindow && dataWindow.document && dataWindow.document.body != null )
+	{
+		//var loadImage = document.createElement('img');
+		//loadImage.src = "file://localhost/Users/ondovb/Krona/KronaTools/img/loading.gif";
+		//loadImage.id = "loading";
+		//loadImage.alt = "Loading...";
+		//dataWindow.document.body.appendChild(loadImage);
+		dataWindow.document.body.innerHTML =
+			'<img id="loading" src="' + loadingImage + '" alt="Loading..."></img>';
+	}
+	
+	var scripts = document.createElement('div');
+	scripts.id = 'data';
+	document.body.appendChild(scripts);
+	
+	var files = focusNode.getData(indexData, summary);
+	
+	var date = new Date();
+	var time = date.getTime();
+	
+	for ( var i = 0; i < files.length; i++ )
+	{
+		var script = document.createElement('script');
+		script.src = files[i] + '?' + time;
+		scripts.appendChild(script);
+	}
+	
+	waitForData(dataWindow, files.length, title, time, attributes[indexAttribute].postUrl, attributes[indexAttribute].postVar);
+	
+	return false;
+}
+
+function showList(indexList, indexAttribute, summary)
+{
+	var list = focusNode.getList(indexList, summary);
+	
+	if ( attributes[indexAttribute].postUrl != undefined )
+	{
+		post(attributes[indexAttribute].postUrl, attributes[indexAttribute].postVar, list.join(','));
+	}
+	else
+	{
+		var dataWindow = window.open('', '_blank');
+		
+		if ( true || navigator.appName == 'Microsoft Internet Explorer' ) // :(
+		{
+			dataWindow.document.open();
+			dataWindow.document.write('<pre>' + list.join('\n') + '</pre>');
+			dataWindow.document.close();
+		}
+		else
+		{
+			var pre = document.createElement('pre');
+			dataWindow.document.body.appendChild(pre);
+			pre.innerHTML = list;
+		}
+		
+		dataWindow.document.title = 'Krona - ' + attributes[indexAttribute].displayName + ' - ' + focusNode.name;
+	}
+}
+
+function snapshot()
+{
+	svg = svgHeader();
+	
+	resetKeyOffset();
+	
+	snapshotMode = true;
+	
+	selectedNode.draw(false, true);
+	selectedNode.draw(true, true);
+	
+	if ( focusNode != 0 && focusNode != selectedNode )
+	{
+		context.globalAlpha = 1;
+		focusNode.drawHighlight(true);
+	}
+	
+	if ( hueDisplayName && useHue() )
+	{
+		drawLegendSVG();
+	}
+	
+	snapshotMode = false;
+	
+	svg += svgFooter();
+	
+	snapshotWindow = window.open
+	(
+		'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg),
+		'_blank'
+	);
+/*	var data = window.open('data:text/plain;charset=utf-8,hello', '_blank');
+	var data = window.open('', '_blank');
+	data.document.open('text/plain');
+	data.document.write('hello');
+	data.document.close();
+	var button = document.createElement('input');
+	button.type = 'button';
+	button.value = 'save';
+	button.onclick = save;
+	data.document.body.appendChild(button);
+//	snapshotWindow.document.write(svg);
+//	snapshotWindow.document.close();
+*/	
+}
+
+function save()
+{
+	alert(document.body.innerHTML);
+}
+
+function spacer()
+{
+	if ( snapshotMode )
+	{
+		return '   ';
+	}
+	else
+	{
+		return '   ';
+	}
+}
+
+function suppressEvent(e)
+{
+	e.cancelBubble = true;
+	if (e.stopPropagation) e.stopPropagation();
+}
+
+function svgFooter()
+{
+	return '</svg>';
+}
+
+function svgHeader()
+{
+	var patternWidth = fontSize * .6;//radius / 50;
+	
+	return '\
+<?xml version="1.0" standalone="no"?>\
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" \
+	"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\
+<svg width="' + imageWidth + '" height="' + imageHeight + '" version="1.1"\
+	xmlns="http://www.w3.org/2000/svg">\
+<title>Krona (snapshot) - ' +
+(datasets > 1 ? datasetNames[currentDataset] + ' - ' : '') + selectedNode.name +
+'</title>\
+<defs>\
+	<style type="text/css">\
+	text {font-size: ' + fontSize + 'px; font-family: ' + fontFamily + '; dominant-baseline:central}\
+	path {stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	path.wedge {stroke:none}\
+	path.line {fill:none;stroke:black;}\
+	line {stroke:black;stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	line.tick {stroke-width:' + thinLineWidth * fontSize / 6 + ';}\
+	line.pattern {stroke-width:' + thinLineWidth * fontSize / 18 + ';}\
+	circle {fill:none;stroke:black;stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	rect {stroke:black;stroke-width:' + thinLineWidth * fontSize / 12 + ';}\
+	.highlight {stroke:black;stroke-width:'+ highlightLineWidth * fontSize / 12 + ';}\
+	.searchHighlight {fill:rgb(255, 255, 100);stroke:none;}\
+	</style>\
+<pattern id="hiddenPattern" patternUnits="userSpaceOnUse" \
+x="0" y="0" width="' + patternWidth + '" height="' + patternWidth + '">\
+<line class="pattern" x1="0" y1="0" x2="' + patternWidth / 2 + '" y2="' + patternWidth / 2 + '"/>\
+<line class="pattern" x1="' + patternWidth / 2 + '" y1="' + patternWidth +
+'" x2="' + patternWidth + '" y2="' + patternWidth / 2 + '"/>\
+</pattern>\
+</defs>\
+';
+}
+
+function svgText(text, x, y, anchor, bold, color)
+{
+	if ( typeof(anchor) == 'undefined' )
+	{
+		anchor = 'start';
+	}
+	
+	if ( color == undefined )
+	{
+		color = 'black';
+	}
+	
+	return '<text x="' + x + '" y="' + y +
+		'" style="font-color:' + color + ';font-weight:' + (bold ? 'bold' : 'normal') +
+		'" text-anchor="' + anchor + '">' + text + '</text>';
+}
+
+function toggleKeys()
+{
+	if ( showKeys )
+	{
+		keyControl.value = '…';
+		showKeys = false;
+	}
+	else
+	{
+		keyControl.value = 'x';
+		showKeys = true;
+	}
+	
+	updateKeyControl();
+	
+	if ( progress == 1 )
+	{
+		draw();
+	}
+}
+
+function update()
+{
+	if ( ! head )
+	{
+		return;
+	}
+	
+	if ( mouseDown && focusNode != selectedNode )
+	{
+		var date = new Date();
+		
+		if ( date.getTime() - mouseDownTime > quickLookHoldLength )
+		{
+			if ( focusNode.hasChildren() )
+			{
+				expand(focusNode);
+				quickLook = true;
+			}
+		}
+	}
+	
+	if ( updateViewNeeded )
+	{
+		resize();
+		mouseX = -1;
+		mouseY = -1;
+		
+		collapse = collapseCheckBox.checked;
+		compress = true;//compressCheckBox.checked;
+		shorten = true;//shortenCheckBox.checked;
+		
+		checkSelectedCollapse();
+		updateMaxAbsoluteDepth();
+		
+		if ( focusNode.getCollapse() || focusNode.depth > maxAbsoluteDepth )
+		{
+			setFocus(selectedNode);
+		}
+		else
+		{
+			setFocus(focusNode);
+		}
+		
+		updateView();
+		
+		updateViewNeeded = false;
+	}
+	
+	var date = new Date();
+	progress = (date.getTime() - tweenStartTime) / tweenLength;
+//	progress += .01;
+	
+	if ( progress >= 1 )
+	{
+		progress = 1;
+	}
+	
+	if ( progress != progressLast )
+	{
+		tweenFactor =// progress;
+			(1 / (1 + Math.exp(-tweenCurvature * (progress - .5))) - .5) /
+			(tweenMax - .5) / 2 + .5;
+		
+		if ( progress == 1 )
+		{
+			snapshotButton.disabled = false;
+			zoomOut = false;
+			
+			//updateKeyControl();
+			
+			if ( ! quickLook )
+			{
+				//checkHighlight();
+			}
+			
+			
+			if ( fpsDisplay )
+			{
+				fpsDisplay.innerHTML = 'fps: ' + Math.round(tweenFrames * 1000 / tweenLength);
+			}
+		}
+		
+		draw();
+	}
+	
+	progressLast = progress;
+}
+
+function updateDatasetButtons()
+{
+	if ( datasets == 1 )
+	{
+		return;
+	}
+	
+	var node = selectedNode ? selectedNode : head;
+	
+	datasetButtonLast.disabled =
+		node.attributes[magnitudeIndex][lastDataset] == 0;
+	
+	datasetButtonPrev.disabled = true;
+	datasetButtonNext.disabled = true;
+	
+	for ( var i = 0; i < datasets; i++ )
+	{
+		var disable = node.attributes[magnitudeIndex][i] == 0;
+		
+		datasetDropDown.options[i].disabled = disable;
+		
+		if ( ! disable )
+		{
+			if ( i != currentDataset )
+			{
+				datasetButtonPrev.disabled = false;
+				datasetButtonNext.disabled = false;
+			}
+		}
+	}
+}
+
+function updateDatasetWidths()
+{
+	if ( datasets > 1 )
+	{
+		for ( var i = 0; i < datasets; i++ )
+		{
+			context.font = fontBold;
+			var dim = context.measureText(datasetNames[i]);
+			datasetWidths[i] = dim.width;
+		}
+	}
+}
+
+function updateKeyControl()
+{
+	if ( keys == 0 )//|| progress != 1 )
+	{
+		keyControl.style.visibility = 'hidden';
+	}
+	else
+	{
+		keyControl.style.visibility = 'visible';
+		keyControl.style.right = margin + 'px';
+		
+		if ( showKeys )
+		{
+			keyControl.style.top =
+				imageHeight -
+				(
+					keys * (keySize + keyBuffer) -
+					keyBuffer +
+					margin +
+					keyControl.clientHeight * 1.5
+				) + 'px';
+		}
+		else
+		{
+			keyControl.style.top =
+				(imageHeight - margin - keyControl.clientHeight) + 'px';
+		}
+	}
+}
+
+function updateView()
+{
+	if ( selectedNode.depth > maxAbsoluteDepth - 1 )
+	{
+		maxAbsoluteDepth = selectedNode.depth + 1;
+	}
+	
+	highlightedNode = selectedNode;
+	
+	angleFactor = 2 * Math.PI / (selectedNode.magnitude);
+	
+	maxPossibleDepth = Math.floor(gRadius / (fontSize * minRingWidthFactor));
+	
+	if ( maxPossibleDepth < 4 )
+	{
+		maxPossibleDepth = 4;
+	}
+	
+	var minRadiusInner = fontSize * 8 / gRadius;
+	var minRadiusFirst = fontSize * 6 / gRadius;
+	var minRadiusOuter = fontSize * 5 / gRadius;
+	
+	if ( .25 < minRadiusInner )
+	{
+		minRadiusInner = .25;
+	}
+	
+	if ( .15 < minRadiusFirst )
+	{
+		minRadiusFirst = .15;
+	}
+	
+	if ( .15 < minRadiusOuter )
+	{
+		minRadiusOuter = .15;
+	}
+	
+	// visibility of nodes depends on the depth they are displayed at,
+	// so we need to set the max depth assuming they can all be displayed
+	// and iterate it down based on the deepest child node we can display
+	//
+	var maxDepth;
+	var newMaxDepth = selectedNode.getMaxDepth() - selectedNode.getDepth() + 1;
+	//
+	do
+	{
+		maxDepth = newMaxDepth;
+		
+		if ( ! compress && maxDepth > maxPossibleDepth )
+		{
+			maxDepth = maxPossibleDepth;
+		}
+		
+		if ( compress )
+		{
+			compressedRadii = new Array(maxDepth);
+			
+			compressedRadii[0] = minRadiusInner;
+			
+			var offset = 0;
+			
+			while
+			(
+				lerp
+				(
+					Math.atan(offset + 2),
+					Math.atan(offset + 1),
+					Math.atan(maxDepth + offset - 1),
+					minRadiusInner,
+					1 - minRadiusOuter
+				) - minRadiusInner > minRadiusFirst &&
+				offset < 10
+			)
+			{
+				offset++;
+			}
+			
+			offset--;
+			
+			for ( var i = 1; i < maxDepth; i++ )
+			{
+				compressedRadii[i] = lerp
+				(
+					Math.atan(i + offset),
+					Math.atan(offset),
+					Math.atan(maxDepth + offset - 1),
+					minRadiusInner,
+					1 - minRadiusOuter
+				)
+			}
+		}
+		else
+		{
+			nodeRadius = 1 / maxDepth;
+		}
+		
+		newMaxDepth = selectedNode.maxVisibleDepth(maxDepth);
+		
+		if ( compress )
+		{
+			if ( newMaxDepth <= maxPossibleDepth )
+			{
+//				compress
+			}
+		}
+		else
+		{
+			if ( newMaxDepth > maxPossibleDepth )
+			{
+				newMaxDepth = maxPossibleDepth;
+			}
+		}
+	}
+	while ( newMaxDepth < maxDepth );
+	
+	maxDisplayDepth = maxDepth;
+	
+	lightnessFactor = (lightnessMax - lightnessBase) / (maxDepth > 8 ? 8 : maxDepth);
+	keys = 0;
+	
+	nLabelOffsets = new Array(maxDisplayDepth - 1);
+	labelOffsets = new Array(maxDisplayDepth - 1);
+	labelLastNodes = new Array(maxDisplayDepth - 1);
+	labelFirstNodes = new Array(maxDisplayDepth - 1);
+	
+	for ( var i = 0; i < maxDisplayDepth - 1; i++ )
+	{
+		if ( compress )
+		{
+			if ( i == maxDisplayDepth - 1 )
+			{
+				nLabelOffsets[i] = 0;
+			}
+			else
+			{
+				var width =
+					(compressedRadii[i + 1] - compressedRadii[i]) *
+					gRadius;
+				
+				nLabelOffsets[i] = Math.floor(width / fontSize / 1.2);
+				
+				if ( nLabelOffsets[i] > 2 )
+				{
+					nLabelOffsets[i] = min
+					(
+						Math.floor(width / fontSize / 1.75),
+						5
+					);
+				}
+			}
+		}
+		else
+		{
+			nLabelOffsets[i] = Math.max
+			(
+				Math.floor(Math.sqrt((nodeRadius * gRadius / fontSize)) * 1.5),
+				3
+			);
+		}
+		
+		labelOffsets[i] = Math.floor((nLabelOffsets[i] - 1) / 2);
+		labelLastNodes[i] = new Array(nLabelOffsets[i] + 1);
+		labelFirstNodes[i] = new Array(nLabelOffsets[i] + 1);
+		
+		for ( var j = 0; j <= nLabelOffsets[i]; j++ )
+		{
+			// these arrays will allow nodes with neighboring labels to link to
+			// each other to determine max label length
+			
+			labelLastNodes[i][j] = 0;
+			labelFirstNodes[i][j] = 0;
+		}
+	}
+	
+	fontSizeText.innerHTML = fontSize;
+	fontNormal = fontSize + 'px ' + fontFamily;
+	context.font = fontNormal;
+	fontBold = 'bold ' + fontSize + 'px ' + fontFamily;
+	tickLength = fontSize * .7;
+	
+	head.setTargets(0);
+	
+	keySize = ((imageHeight - margin * 3) * 1 / 2) / keys * 3 / 4;
+	
+	if ( keySize > fontSize * maxKeySizeFactor )
+	{
+		keySize = fontSize * maxKeySizeFactor;
+	}
+	
+	keyBuffer = keySize / 3;
+	
+	fontSizeLast = fontSize;
+	
+	if ( datasetChanged )
+	{
+		datasetChanged = false;
+	}
+	else
+	{
+		datasetAlpha.start = 0;
+	}
+	
+	var date = new Date();
+	tweenStartTime = date.getTime();
+	progress = 0;
+	tweenFrames = 0;
+	
+	updateKeyControl();
+	updateDatasetWidths();
+	
+	document.title = 'Krona - ' + selectedNode.name;
+	updateNavigationButtons();
+	snapshotButton.disabled = true;
+	
+	maxAbsoluteDepthText.innerHTML = maxAbsoluteDepth - 1;
+	
+	maxAbsoluteDepthButtonDecrease.disabled = (maxAbsoluteDepth == 2);
+	maxAbsoluteDepthButtonIncrease.disabled = (maxAbsoluteDepth == head.maxDepth);
+	
+	if ( collapse != collapseLast && search.value != '' )
+	{
+		onSearchChange();
+		collapseLast = collapse;
+	}
+}
+
+function updateMaxAbsoluteDepth()
+{
+	while ( selectedNode.depth > maxAbsoluteDepth - 1 )
+	{
+		selectedNode = selectedNode.getParent();
+	}
+}
+
+function updateNavigationButtons()
+{
+	backButton.disabled = (nodeHistoryPosition == 0);
+//	upButton.disabled = (selectedNode.getParent() == 0);
+	forwardButton.disabled = (nodeHistoryPosition == nodeHistory.length);
+}
+
+function useHue()
+{
+	return useHueCheckBox && useHueCheckBox.checked;
+}
+/*
+function zoomOut()
+{
+	return (
+		selectedNodeLast != 0 &&
+		selectedNodeLast.getDepth() < selectedNode.getDepth());
+}
+*/
\ No newline at end of file
diff --git a/KronaTools/updateAccessions.sh b/KronaTools/updateAccessions.sh
new file mode 100755
index 0000000..da32b12
--- /dev/null
+++ b/KronaTools/updateAccessions.sh
@@ -0,0 +1,11 @@
+#! /bin/bash
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+ktPath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
+
+$ktPath/updateTaxonomy.sh --accessions $@
diff --git a/KronaTools/updateTaxonomy.sh b/KronaTools/updateTaxonomy.sh
new file mode 100755
index 0000000..78a1890
--- /dev/null
+++ b/KronaTools/updateTaxonomy.sh
@@ -0,0 +1,311 @@
+#! /bin/bash
+
+# Copyright © 2011, Battelle National Biodefense Institute (BNBI);
+# all rights reserved. Authored by: Brian Ondov, Nicholas Bergman, and
+# Adam Phillippy
+#
+# See the LICENSE.txt file included with this software for license information.
+
+if [ "$(uname)" == "Darwin" ]
+then
+    MD5="md5 -r"
+else # Assume linux
+    MD5=md5sum
+fi
+
+makefileAcc2taxid="scripts/accession2taxid.make"
+makefileTaxonomy="scripts/taxonomy.make"
+
+command -v curl >/dev/null 2>&1 || \
+	{ echo >&2 "ERROR: Curl (http://curl.haxx.se) is required."; exit 1; }
+
+while [ "$#" -ne 0 ]
+do
+	if [ $1 == "--help" ] || [ $1 == "-h" ]
+	then
+		echo
+		echo "updateTaxonomy.sh [options...] [/custom/dir]"
+		echo
+		echo "   [/custom/dir]  Taxonomy will be built in this directory instead of the"
+		echo "                  directory specified during installation. This custom"
+		echo "                  directory can be referred to with -tax in import scripts."
+		echo
+		echo "   --only-fetch   Only download source files; do not build."
+		echo
+		echo "   --only-build   Assume source files exist; do not fetch."
+		echo
+		echo "   --preserve     Do not remove source files after build."
+		echo
+		exit
+	elif [ $1 == "--only-fetch" ]
+	then
+		localPull=1
+	elif [ $1 == "--only-build" ]
+	then
+		local=1
+	elif [ $1 == "--preserve" ]
+	then
+		preserve=1
+	elif [ $1 == "--accessions" ]
+	then
+		accessions=1
+	elif [ "${1:0:1}" == "-" ]
+	then
+		echo "Unrecognized option: \"$1\". See help (--help or -h)"
+		exit
+	else
+		taxonomyPath=$1
+	fi
+
+	shift
+done
+
+function die
+{
+	echo
+	echo "Update failed."
+	echo "   $1"
+	echo
+	exit 1
+}
+
+function clean
+{
+	aFile=$1
+
+	if [ -e $aFile ]
+	then
+		rm $aFile
+	fi
+}
+
+function fetch
+{
+	name="$1"
+	description="$2"
+	prefix="$3"
+	timeDependencies="$4"
+	retry="$5"
+	
+	timestring=""
+	depDesc=""
+	
+	if [ "$retry" != "1" ]
+	then
+		for dep in $name $timeDependencies
+		do
+			if [ -s "$dep" ]
+			then
+				timestring=" -z $dep"
+				depDesc=" (if newer than $dep)"
+				break
+			fi
+		done
+	fi
+	
+	echo "Fetching $description$depDesc..."
+	
+	curl$timestring -s -R --retry 1 -o $name ftp://ftp.ncbi.nih.gov/pub/taxonomy/$prefix/$name
+	return=$?
+
+	if [ $return == "23" ]
+	then
+		die "Could not write '$taxonomyPath/$name'. Do you have permission?"
+	fi
+
+	if [ $return != "0" ]
+	then
+		die "Is your internet connection okay?"
+	fi
+
+	if [ -e "$name" ]
+	then
+		echo "   Fetching checksum..."
+
+		curl -s -R --retry 1 -o $name.md5 ftp://ftp.ncbi.nih.gov/pub/taxonomy/$prefix/$name.md5
+		checksum=$($MD5 $name | cut -d ' ' -f 1)
+		checksumRef=$(cut -d ' ' -f 1 $name.md5)
+		rm $name.md5
+
+		if [ $checksum == $checksumRef ]
+		then
+			echo "   Checksum for $name matches server."
+		else
+			if [ "$retry" == "1" ]
+			then
+				die "Checksum for $name still does not match server after retry."
+			else
+				echo "Checksum for $name does not match server. Retrying..."
+				fetch "$name" "$description" "$prefix" "$timeDependcies" 1
+			fi
+		fi
+	fi
+}
+
+if [ "$local" == "1" ] && [ "$localPull" == "1" ]
+then
+	die "Cannot use --only-fetch with --only-build."
+fi
+
+ktPath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
+
+if [ "$taxonomyPath" == "" ]
+then
+	taxonomyPath="$ktPath/taxonomy";
+else
+	if [ ! -d "$taxonomyPath" ]
+	then
+		if [ $local == "1" ]
+		then
+			die "Could not find $taxonomyPath."
+		fi
+
+		echo
+		echo "Creating $taxonomyPath..."
+		echo
+
+		mkdir -p "$taxonomyPath"
+
+		if [ "$?" != "0" ]
+		then
+			die "Could not create '$taxonomyPath'. Do you have permission?"
+		fi
+	fi
+fi
+
+if [ "$accessions" == "1" ] && [ ! -d "$taxonomyPath/accession2taxid" ]
+then
+	mkdir "$taxonomyPath/accession2taxid"
+
+	if [ "$?" != "0" ]
+	then
+		die "Could not create '$taxonomyPath/accession2taxid'. Do you have permission?"
+	fi
+fi
+
+cd $taxonomyPath
+
+if [ "$?" != "0" ]
+then
+	die "Could not enter '$taxonomyPath'."
+fi
+
+ACC2TAXID="
+accession2taxid/dead_nucl.accession2taxid
+accession2taxid/dead_prot.accession2taxid
+accession2taxid/dead_wgs.accession2taxid
+accession2taxid/nucl_est.accession2taxid
+accession2taxid/nucl_gb.accession2taxid
+accession2taxid/nucl_gss.accession2taxid
+accession2taxid/nucl_wgs.accession2taxid
+accession2taxid/prot.accession2taxid
+"
+
+if [ "$local" != "1" ]
+then
+	if [ "$accessions" == "1" ]
+	then
+		fetchAll="$localPull"
+		
+		if [ "$fetchAll" == "" ] && [ ! -e all.accession2taxid.sorted ]
+		then
+			fetchAll=1
+		fi
+		
+		# if any are fetched by timestamp of all.accession2taxid.sorted, all
+		# others must be fetched to rebuild it
+		#
+		if [ "$fetchAll" == "" ]
+		then
+			for unzipped in $ACC2TAXID
+			do
+				fetch $unzipped.gz $unzipped.gz "" "$unzipped all.accession2taxid.sorted"
+				
+				if [ -e $unzipped.gz ]
+				then
+					if [ ! -e all.accession2taxid.sorted ] || [ $unzipped.gz -nt all.accession2taxid.sorted ]
+					then
+						fetchAll=1
+					fi
+				fi
+			done
+		fi
+		#
+		if [ "$fetchAll" == "1" ]
+		then
+			for unzipped in $ACC2TAXID
+			do
+				if [ "$localPull" == "1" ] || [ ! -e $unzipped.gz ] && [ ! -e $unzipped ]
+				then
+					fetch $unzipped.gz $unzipped.gz "" $unzipped
+				fi
+			done
+		fi
+	else
+		fetch taxdump.tar.gz "taxdump.tar.gz" "" "taxdump.tar names.dmp taxonomy.tab"
+	fi
+fi
+
+if [ "$localPull" == "1" ]
+then
+	echo
+	echo "Fetching finished."
+	echo
+	exit
+fi
+
+if [ "$accessions" == "1" ]
+then
+	for base in $ACC2TAXID
+	do
+		if [ ! -e $base ] && [ ! -e $base.gz ]
+		then
+			if [ "$local" == "1" ]
+			then
+				die "Could not find accession2taxid source files in $taxonomyPath."
+			else
+				echo "Accessions up to date."
+				exit 0
+			fi
+		fi
+	done
+	
+	cd accession2taxid
+	
+	make -j 4 PRESERVE="$preserve" -f $ktPath/$makefileAcc2taxid
+
+	if [ "$?" != "0" ]
+	then
+		die "Building accession2taxid failed (see errors above). Issues can be tracked and reported at https://github.com/marbl/Krona/issues."
+	fi
+else
+	if [ -e taxdump.tar ] || [ -e taxdump.tar.gz ] || [ -e names.dmp ]
+	then
+		make KTPATH="$ktPath" PRESERVE="$preserve" -f $ktPath/$makefileTaxonomy
+
+		if [ "$?" != "0" ]
+		then
+			die "Building taxonomy table failed (see errors above). Issues can be tracked and reported at https://github.com/marbl/Krona/issues."
+		fi
+	elif [ "$local" == "1" ]
+	then
+		die "Could not find taxonomy source files in $taxonomyPath."
+	fi
+fi
+
+if [ "$preserve" != "1" ]
+then
+	echo
+	echo "Cleaning up..."
+
+	if [ "$accessions" != "1" ]
+	then
+		make -f $ktPath/$makefileTaxonomy clean
+	else
+		rmdir $ktPath/taxonomy/accession2taxid 2> /dev/null
+	fi
+fi
+
+echo
+echo "Finished."
+echo

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



More information about the debian-med-commit mailing list