Browse Source

Merge branch '7.x-3.x' into 680-tv3-unpublish_button

Stephen Ficklin 4 years ago
parent
commit
b72612099a
28 changed files with 871 additions and 708 deletions
  1. 11 1
      .all-contributorsrc
  2. 60 61
      README.md
  3. 3 3
      docs/contributing/governance.rst
  4. 17 3
      docs/contributing/pull_requests.rst
  5. 1 1
      docs/dev_guide/chado.rst
  6. 1 1
      docs/dev_guide/custom_field.rst
  7. 2 2
      docs/dev_guide/custom_field/custom_formatter.rst
  8. 4 4
      docs/dev_guide/custom_field/manual_field_creation.rst
  9. 1 1
      docs/dev_guide/custom_field/select_vocab_terms.rst
  10. 1 1
      docs/dev_guide/data_structures.rst
  11. 1 1
      docs/dev_guide/introduction.rst
  12. 1 1
      docs/user_guide/bulk_loader.rst
  13. 2 2
      docs/user_guide/content_types/configuring_page_display.rst
  14. 1 1
      docs/user_guide/content_types/field_loading.rst
  15. 1 1
      docs/user_guide/install_tripal/drupal_home.rst
  16. 1 1
      docs/user_guide/install_tripal/server_setup.rst
  17. 1 1
      docs/user_guide/job_management.rst
  18. 1 1
      docs/user_guide/searching/search_api.rst
  19. 129 110
      legacy/tripal_phylogeny/theme/js/tripal_phylogeny.js
  20. 4 4
      tripal/tripal_views_query.inc
  21. 210 210
      tripal_chado/chado_schema/default_schema-1.2-1.3-diff.sql
  22. 2 2
      tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence.inc
  23. 1 1
      tripal_chado/includes/TripalFields/so__transcript/so__transcript_formatter.inc
  24. 105 18
      tripal_chado/includes/TripalImporter/TaxonomyImporter.inc
  25. 1 49
      tripal_chado/includes/tripal_chado.install.inc
  26. 50 33
      tripal_chado/includes/tripal_chado.phylotree.inc
  27. 236 178
      tripal_chado/theme/js/d3.phylogram.js
  28. 23 16
      tripal_chado/theme/js/tripal_phylogeny.js

+ 11 - 1
.all-contributorsrc

@@ -164,7 +164,8 @@
       "avatar_url": "https://avatars0.githubusercontent.com/u/38262122?v=4",
       "profile": "https://github.com/par12005",
       "contributions": [
-        "code"
+        "code",
+        "question"
       ]
     },
     {
@@ -193,6 +194,15 @@
       "contributions": [
         "code"
       ]
+    },
+    {
+      "login": "pgrimaud",
+      "name": "Pierre Grimaud",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/1866496?v=4",
+      "profile": "https://github.com/pgrimaud",
+      "contributions": [
+        "doc"
+      ]
     }
   ],
   "contributorsPerLine": 7,

+ 60 - 61
README.md

@@ -7,76 +7,74 @@
 
 ![alt tag](https://raw.githubusercontent.com/tripal/tripal/7.x-3.x/tripal/theme/images/tripal_logo.png)
 
-Tripal is a toolkit for constructing online biological (genetics, genomics, breeding, etc.) community databases, and Tripal is a member of the [GMOD](http://www.gmod.org) family of tools. **Tripal v3** provides integration with the [GMOD Chado database](http://gmod.org/wiki/Chado_-_Getting_Started) by default.
-
-Genetics, genomics, breeding, and other biological data are increasingly complicated and time-consuming to publish online for others to search, browse and make discoveries with. Tripal provides a framework to reduce the complexity of creating such a site, and provides access to a community of similar groups that share community-standards. The users of Tripal are encouraged to interact to address questions and learn the best practices for sharing, storing, and visualizing complex biological data.
-
-The primary goals of Tripal are to:
-1.	Provide a framework for creating sites that allow display, search, and visualization of biological data, including genetics, genomics, and breeding data;
-2.	Use community-derived standards and ontologies to facilitate continuity between sites and foster collaboration and sharing;
-3.	Provide an out-of-the-box setup for a genomics site to put new genome assemblies and annotations online; and
-4.	Provide Application Programming Interfaces (APIs) to support customized displays, look-and-feel, and new functionality.
-
-
-# Features
-The following major features
-are available in Tripal v3.
-
-* Tripal v3's design is centered around controlled vocabularies and ontologies. 
-  This allows for greater integration with the semantic web and will help
-  support data exchange between Tripal sites.
-* RESTful web services.  Tripal v3 introduces RESTful web services for Tripal.
-  The resources provided by these web services uses JSON-LD and WC3 Hydra 
-  vocabulary to deliver content. 
-* Tripal v3 introduces new content pages. In older versions of Tripal all 
-  content was provided via Drupal "nodes".  Now content is delivered using
-  new content types (e.g. gene, genetic_marker, organism, germplasm, etc.)
-  and the site admin controls which content types are available on the site. 
-* Chado support:
-  * Tripal v3 represents a major redesign from previous versions.  Previously,
-    Chado was the only storage backend supported. Tripal v3 provides by default
-    support for Chado, but also sports a new design that affords integration of
-    other storage backends (including noSQL options).  
-  * A Chado v1.2 or v1.3 installer
-  * Data loaders for ontologies (controlled vocabularies), GFF files, and 
-    FASTA files, publications (from PubMed and AGIRCOLA). 
-  * Generic Bulk Data Loader Modules allows for creation of custom loaders 
-    without programming (requires an understanding of Chado). 
-  * Supports creation of materialized views for faster data queries.
+Welcome to the home of Tripal Development! If you are thinking to yourself "What is Tripal?", head over to [our website, Tripal.info](http://tripal.info/).
 
+# Current Status
 
-# Required Dependencies
-* Drupal: 
-  * Drupal 7.x
-  * Drupal core modules: Search, Path and PHP modules.
-  * Drupal contributed modules: 
-    * [Views](http://drupal.org/project/views)
-    * [Entity API](http://drupal.org/project/entity)
-* PostgreSQL
-* PHP 5.5+
-* UNIX/Linux
+ - Recommended Version: ![GitHub release (latest by date)](https://img.shields.io/github/v/release/tripal/tripal?color=brightgreen)
+ - Development:
+    - [![Tripal 3](https://img.shields.io/badge/dev-7.x--3.x-yellow)](https://github.com/tripal/tripal): Focus is on bug fixes
+    - [![Tripal 4](https://img.shields.io/badge/dev-7.x--4.x-yellow)](https://github.com/tripal/t4d8): Full upgrade to Drupal 8/9 (development in [T4D8 Repository](https://github.com/tripal/t4d8)).
+ - Tripal ![Tripal 1.x](https://img.shields.io/badge/unsupported-7.x--1.x-red) and ![Tripal 2.x](https://img.shields.io/badge/unsupported-7.x--2.x-red) are no longer supported by the Project Management Committee, although we will accept community submitted fixes for Tripal 2.x.
+
+ # Resources
+
+  - For information on **how to use Tripal** through the Administrative Interface: [Tripal Users Guide](https://tripal.readthedocs.io/en/latest/user_guide.html)
+  - For help **extending Tripal** or understanding how it works: [Tripal Developers Guide](https://tripal.readthedocs.io/en/latest/dev_guide.html)
+  - To check if another group already developed the functionality you need: [Listing of **Available Extension Modules**](https://tripal.readthedocs.io/en/latest/extensions.html)
+  - Tripal is developed by a world-wide community! See the [description of our **Governance Structure**](https://tripal.readthedocs.io/en/latest/contributing/governance.html)
+  - If you are the head of a research group looking to fund Tripal Development: [Guide to **Funding Proposal** Development](https://tripal.readthedocs.io/en/latest/contributing/funding.html)
+  - For how to **install Tripal**, follow the instructions in the online Tripal User's Guide for [Tripal v2](https://tripal.info/tutorials/v2.x/installation) or [Tripal v3](https://tripal.readthedocs.io/en/latest/user_guide.html).
+  - For how to **upgrade from Tripal 2 to Tripal 3**, follow the [Upgrade Instructions](https://tripal.readthedocs.io/en/latest/user_guide/install_tripal/upgrade_from_tripal2.html) in the Tripal v3 User's Guide.
+
+# Contribution
 
+Looking to contribute? That's Amazing -Welcome!!! Here's a quick run-down to get you started:
 
-# Installation
-Please follow the instructions in the online Tripal User's Guide for [Tripal v2](https://tripal.info/tutorials/v2.x/installation) or [Tripal v3](https://tripal.readthedocs.io/en/latest/user_guide.html).
+ - We welcome all contributions!
+ - This github issue queue is open to: bug reports, usability concerns, performance issues, site administration or development questions, data storage discussions, etc.
+ - We ask that questions/concerns/bugs with **extension modules** be addressed in their respective repositories (including those under the Tripal organization).
+ - For **feature request**, please open an issue with detailed use cases and description. We would love to help you design a generic solution for the community whether it belongs in Tripal Core or an Extension module! Please wait to submit a PR until the Project Management Committee (PMC) indicates it is generally applicable and should be included in Core.
+ - For **potential bugs or concerns**, please open an issue being as descriptive as possible. Screenshots and steps to reproduce will help us, help you! If you know how to fix the issue, feel free to submit a pull request (PR) linked to the issue!
+ - For **documentation** contributions, click the "Edit on Github" link at the top of the page you want to improve! [Instructions for our flavour of ReadtheDocs can be found on ReadtheDocs](https://tripal.readthedocs.io/en/latest/contributing/documentation.html).
+ - See our quickstart if you need help on how to submit a PR: [ReadtheDocs, how to create a PR](https://tripal.readthedocs.io/en/latest/contributing/pull_requests.html#how-to-create-a-pr).
+ - Click on issues > New Issue for helpful issue templates.
+ - For Tripal 4 (Drupal 8/9), see the [T4D8 repository](https://github.com/tripal/t4d8).
 
+For more detailed guidelines see our [full Contribution Documentation](https://tripal.readthedocs.io/en/latest/contributing/pull_requests.html)!
 
-# Upgrade from Tripal v2.x to v3.x
-Please follow the [Upgrade Instructions](https://tripal.readthedocs.io/en/latest/user_guide/install_tripal/upgrade_from_tripal2.html) in the Tripal v3 User's Guide
 
+# Github Communication Tips
 
-# Customization
-Tripal can be used “as is” but also allows for complete customization.
-PHP-based template files are provided for all data types to allow for 
-precise customizations as required by the community. A well-developed 
-Tripal API provides a uniform set of variables and functions for 
-accessing any and all data within the Chado database. See the Tripal 3.x
-Developer's Handbook for additional details.
+ - Don’t be afraid to mention people (@username) who are knowledgeable on the topic or invested. We are academics and overcommitted, it’s too easy for issues to go unanswered: don’t give up on us!
+ - Likewise, don’t be shy about bumping an issue if no one responds after a few days. Balancing responsibilities is hard.
+ - Want to get more involved? Issues marked with “Good beginner issue” are a good place to start if you want to try your hand at submitting a PR.
+ - Everyone is encouraged/welcome to comment on the issue queue! Tell us if you
+     - are experiencing the same problem
+     - have tried a suggested fix
+     - know of a potential solution or work-around
+     - have an opinion, idea or feedback of any kind!
+ - Be kind when interacting with others on Github! (see Code of Conduct below for further guidelines). We want to foster a welcoming, inclusive community!
+     - Constructive criticism is welcome and encouraged but should be worded such that it is helpful :-) Direct criticism towards the idea or solution rather than the person and focus on alternatives or improvements.
 
+# Code of Conduct
+
+Be nice! If that’s insufficient, Tripal community defers to https://www.contributor-covenant.org/
+
+# Required Dependencies
+* Drupal:
+  * Drupal 7.x
+  * Drupal core modules: Search, Path and PHP modules.
+  * Drupal contributed modules:
+    * [Views](http://drupal.org/project/views)
+    * [Entity API](http://drupal.org/project/entity)
+* PostgreSQL 9.3 or higher (9.5 required for Chado 1.2 to 1.3 upgrade)
+* PHP 5.5+
+* UNIX/Linux
 
 # Development Testing
 
-To run PHP unit tests on your local system, run `composer install` to install developer-specific requirements.  Next, create a `.env` file in your `/Tests/` directory that defines the `DRUPAL_ROOT` variable, for example 
+To run PHP unit tests on your local system, run `composer install` to install developer-specific requirements.  Next, create a `.env` file in your `/Tests/` directory that defines the `DRUPAL_ROOT` variable, for example
 
 ```
 DRUPAL_ROOT=/var/www/html
@@ -85,7 +83,7 @@ Then run PHPUnit from your root Tripal directory.
 
 PHPUnit tests will also be run in the Travis CI build.
 
-Read our [testing guidelines](tests/README.md)
+Read our [testing guidelines](https://tripal.readthedocs.io/en/latest/contributing/tests.html).
 
 ## Contributors
 
@@ -115,10 +113,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
   </tr>
   <tr>
     <td align="center"><a href="http://www.vcru.wisc.edu/simonlab/sdata/software/index.html"><img src="https://avatars3.githubusercontent.com/u/8419404?v=4" width="100px;" alt=""/><br /><sub><b>Douglas Senalik</b></sub></a><br /><a href="https://github.com/tripal/tripal/commits?author=dsenalik" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/par12005"><img src="https://avatars0.githubusercontent.com/u/38262122?v=4" width="100px;" alt=""/><br /><sub><b>par12005</b></sub></a><br /><a href="https://github.com/tripal/tripal/commits?author=par12005" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/par12005"><img src="https://avatars0.githubusercontent.com/u/38262122?v=4" width="100px;" alt=""/><br /><sub><b>par12005</b></sub></a><br /><a href="https://github.com/tripal/tripal/commits?author=par12005" title="Code">💻</a> <a href="#question-par12005" title="Answering Questions">💬</a></td>
     <td align="center"><a href="http://sofiarobb.com"><img src="https://avatars0.githubusercontent.com/u/1072991?v=4" width="100px;" alt=""/><br /><sub><b>Sofia Robb</b></sub></a><br /><a href="https://github.com/tripal/tripal/commits?author=srobb1" title="Code">💻</a></td>
     <td align="center"><a href="https://github.com/katherynbuble"><img src="https://avatars3.githubusercontent.com/u/59714566?v=4" width="100px;" alt=""/><br /><sub><b>katherynbuble</b></sub></a><br /><a href="https://github.com/tripal/tripal/commits?author=katherynbuble" title="Code">💻</a></td>
     <td align="center"><a href="https://github.com/risharde"><img src="https://avatars3.githubusercontent.com/u/33866403?v=4" width="100px;" alt=""/><br /><sub><b>risharde</b></sub></a><br /><a href="https://github.com/tripal/tripal/commits?author=risharde" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/pgrimaud"><img src="https://avatars1.githubusercontent.com/u/1866496?v=4" width="100px;" alt=""/><br /><sub><b>Pierre Grimaud</b></sub></a><br /><a href="https://github.com/tripal/tripal/commits?author=pgrimaud" title="Documentation">📖</a></td>
   </tr>
 </table>
 
@@ -126,4 +125,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 <!-- prettier-ignore-end -->
 <!-- ALL-CONTRIBUTORS-LIST:END -->
 
-This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
+This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

+ 3 - 3
docs/contributing/governance.rst

@@ -24,7 +24,7 @@ These are developers who are extending Tripal. Extension contributors are encour
 
 Core Code Contributors
 ------------------------
-Core Code Contributors are active members of the Tripal community who make suggestions to improve and/or contribute code to Tripal Core. Core Code Contributors are encouraged to submit pull requests to the Tripal core and attend monthly user calls. For more information, see the `Guidelines for Contributing to Tripal core <https://tripal.readthedocs.io/en/latest/dev_guide/contributing/pull_requests.html>`_.
+Core Code Contributors are active members of the Tripal community who make suggestions to improve and/or contribute code to Tripal Core. Core Code Contributors are encouraged to submit pull requests to the Tripal core and attend monthly user calls. For more information, see the `Guidelines for Contributing to Tripal core <https://tripal.readthedocs.io/en/latest/contributing/pull_requests.html>`_.
 
 Responsibilities include:
  - Monitor Tripal core issue queue.
@@ -39,7 +39,7 @@ Responsibilities include:
  - Monitor Tripal core issue queue.
  - Review and merge pull requests.
 
-See the `guidelines for contributors <https://tripal.readthedocs.io/en/latest/dev_guide/contributing/pull_requests.html>`_ for more details.
+See the `guidelines for contributors <https://tripal.readthedocs.io/en/latest/contributing/pull_requests.html>`_ for more details.
 
 The Tripal Project Management Committee (PMC)
 ------------------------------------------------
@@ -55,7 +55,7 @@ Responsibilities include:
      - designing a module-specific REST API,
      - new technologies or libraries used by the core code.
  - Avoid feature bloat; judge what contributions benefit many versus those that are specific to the needs of the contributor.
- - Final approval of submitting guidelines (see `guidelines for contribution <https://tripal.readthedocs.io/en/latest/dev_guide/contributing.html>`_).
+ - Final approval of submitting guidelines (see `guidelines for contribution <https://tripal.readthedocs.io/en/latest/contributing/pull_requests.html>`_).
  - Set coding standards.
  - Ensure Tripal remains generic and useful to a wide range of groups.
 

+ 17 - 3
docs/contributing/pull_requests.rst

@@ -63,7 +63,7 @@ The goal of this document is to make it easy for **A)** contributors to make pul
 - PRs that address a specific issue **must** link to the related issue page.
     - In almost every case, there should be an issue for a PR.  This allows feedback and discussion before the coding happens.  Not grounds to reject, but encourage users to create issues at start of their PR.  Better late than never :).
 - Each PR **must** be tested/approved by at least 1 contributor, if approved, a "trusted committer" will merge the PR.
-    - Testers **should** describe how the testing was performed if applicable (allows others to replicate the test).    
+    - Testers **should** describe how the testing was performed if applicable (allows others to replicate the test).
     - While Tripal's review body is small, the code review must be a thorough functional test.
     - At the Project Management Committee's (PMC) discretion, a PR may be subject to a non-functional review.  Generally these are small and obvious commits.
     - Tripal's guiding philosophy is to encourage open contribution.  With this in mind, committers should **work with contributors** to resolve issues in their PRs.  PRs that will not be merged should be closed, **transparently citing** the reason for closure.  In an ideal world, features that would be closed are discouraged at the **issue phase** before the code is written!
@@ -81,9 +81,23 @@ The goal of this document is to make it easy for **A)** contributors to make pul
 - PRs for new feature should remain open until adequately discussed (see guidelines below) and approved by a vote (all members of the PMC must vote in favour).
 
 
-.. note::
+How to create a PR
+^^^^^^^^^^^^^^^^^^^^^
+
+There are great instructions on creating a PR on `Digital Ocean: How To Create a Pull Request on GitHub <https://www.digitalocean.com/community/tutorials/how-to-create-a-pull-request-on-github>`_.
+
+**The tl;dr version:**
+
+1. `Fork the repository <https://docs.github.com/en/github/getting-started-with-github/fork-a-repo>`_ or `update an existing fork <https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork>`_
+2. `Clone <https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository>`_ the fork
+3. `Create a branch <https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging>`_ specific to your change: ``[issue\_number]-[tripal\_version]-[short\_description]``
+4. Make your changes, `committing <https://git-scm.com/docs/git-commit#_examples>`_ often with useful commit messages.
+5. `Push <https://git-scm.com/docs/git-push#_examples>`_ your changes to your fork.
+6. `Create a PR by going to your fork <https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork>`_: target should be ``tripal:7.x-3.x``. For specifics, see guidelines above.
+
+.. note:
 
-  If you need more instructions creating a pull request, see for example the `KnowPulse workflow <https://knowpulse.readthedocs.io/en/latest/developer_docs/dev_workflow.html#workflow>`_
+  If you are a `committer <>`_, you can clone the Tripal repository directly with no need to create or maintain a fork. Please make sure you are always creating new branches off of ``7.x-3.x`` and that you have pulled all recent changes to ``7.x-3.x`` before creating a new branch.
 
 How PRs and Issues are Handled
 ------------------------------

+ 1 - 1
docs/dev_guide/chado.rst

@@ -11,7 +11,7 @@ The Chado Query API
 
 Provides an API for querying of chado including inserting, updating, deleting and selecting from specific chado tables. There is also a generic function, ``chado_query()``, to execute and SQL statement on chado. It is ideal to use these functions to interact with chado in order to keep your module compatible with both local & external chado databases. Furthermore, it ensures connection to the chado database is taken care of for you.
 
-Generic Queries to a specifc chado table
+Generic Queries to a specific chado table
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Selecting Records

+ 1 - 1
docs/dev_guide/custom_field.rst

@@ -5,7 +5,7 @@ The most common way that new content will be added to an existing site is by cre
 
 By default Tripal v3 provides many fields for display of Chado data. However, you may find that these fields do not display data as you want, or you want to display data that the current fields do not already provide. This section of the Handbook describes how to create new fields that are integrated into the display, search and exchange abilities of both Drupal and Tripal.
 
-If you are already familiar with Drupal fields you may be aware of the API functions and hooks that Drupal provides.  However, for the quantity of fields needed to support biological data, the Drupal API hooks quickly become overwhelming.  Additionally, documentation for fields in the Drupal API can someitmes be difficult to discover when first working with fields.   Therefore, Tripal provides several new PHP classes to simplify creation of fields and to consolidate all functionality into one easy to find set of files.  To develop new fields you should be somewhat familar working with PHP's Object-Oriented Classes. The new classes provided by Tripal are these:
+If you are already familiar with Drupal fields you may be aware of the API functions and hooks that Drupal provides.  However, for the quantity of fields needed to support biological data, the Drupal API hooks quickly become overwhelming.  Additionally, documentation for fields in the Drupal API can someitmes be difficult to discover when first working with fields.   Therefore, Tripal provides several new PHP classes to simplify creation of fields and to consolidate all functionality into one easy to find set of files.  To develop new fields you should be somewhat familiar working with PHP's Object-Oriented Classes. The new classes provided by Tripal are these:
 
 
 +----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

+ 2 - 2
docs/dev_guide/custom_field/custom_formatter.rst

@@ -81,7 +81,7 @@ In summary, the following should be observed when processing the ``$items`` arra
 
 .. warning::
 
-  You should never have SQL statments or any API calls that retreive data in the foramter ``view()`` function. The formatter should strictly format data for viewing.
+  You should never have SQL statements or any API calls that retrieve data in the foramter ``view()`` function. The formatter should strictly format data for viewing.
   
 Creating Pagers
 ~~~~~~~~~~~~~~~
@@ -130,7 +130,7 @@ Now that we have a pager, it has been setup for AJAX and we know the current pag
       '#markup' => $content . $pager,
     );
     
-The settingsForm() Funtion.
+The settingsForm() Function.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Sometimes you may want to provide some control to the site developer for the formatter.  For example, the ``sbo__relationship_formater`` allows the site developer to customize the title that appears above the table that houses relationships and the text the appears if there are no relationships.  By default the title is "Relationships" and the empty text indicates there are no relationships. Both are a bit too generic.  The ``settingsForm()`` function allows you to provide a Drupal form for the field that appears on the **Administer > Strucutre > Tripal Content Types** on any content type's **manage display** page:
 

+ 4 - 4
docs/dev_guide/custom_field/manual_field_creation.rst

@@ -113,7 +113,7 @@ Sometimes a field is meant to provide a visualization or some other functionalit
 
   
   // A boolean specifying that the field will not contain any data. This
-  // should exclude the field from web serivces or downloads.  An example
+  // should exclude the field from web services or downloads.  An example
   // could be a quick search field that appears on the page that redirects
   // the user but otherwise provides no data.
 
@@ -198,7 +198,7 @@ Next, let's initialize our field's value to be empty.  When setting a field valu
     );
 
 
-Notice that our field has some sub elements. The first is 'und'.  This element corresponds to the "language" of the text.  Drupal supports mulitple spoken languages and wants to know the language of text we provide.  For Tripal fields we always use 'und' meaning 'undefined'.   The next element is the delta index number.  Field have a cardinality, or in other words they can have multiple values.  For every value we add we increment that index, always starting at zero.  The last element is our 'value' element and it is here where we put our element. You may notice that our **delta** index is hard coded to 0.  This is because an entity can only always have one organism that it is associated with.  We will never have more than one.
+Notice that our field has some sub elements. The first is 'und'.  This element corresponds to the "language" of the text.  Drupal supports multiple spoken languages and wants to know the language of text we provide.  For Tripal fields we always use 'und' meaning 'undefined'.   The next element is the delta index number.  Field have a cardinality, or in other words they can have multiple values.  For every value we add we increment that index, always starting at zero.  The last element is our 'value' element and it is here where we put our element. You may notice that our **delta** index is hard coded to 0.  This is because an entity can only always have one organism that it is associated with.  We will never have more than one.
 
 Now that we've got some preliminary values and we've initialized our value array we can start adding values!  Before we do though, let's double check that we have a record.  If we don't have a record for this entity, we can't get a value.
 
@@ -412,7 +412,7 @@ The array keys just mentioned fully describe our field to Drupal and Tripal.  Ne
             'required' => FALSE,
           ),
 
-Notice that our field will allow searching, provides a variety of search filter options, is sortable and defines the type as 'xs:string'.  The remaing elements follow the same pattern.  As another example, here is the genus element:
+Notice that our field will allow searching, provides a variety of search filter options, is sortable and defines the type as 'xs:string'.  The remaining elements follow the same pattern.  As another example, here is the genus element:
 
 .. code-block:: php
 
@@ -494,7 +494,7 @@ As described above in the elementInfo function section, some fields and elements
       }
     }
 
-The code above is how the field tells Drupal and Tripal how to find and filter the records that this field corresponds to.  First, we retreive the field alias and operators:and as with the load and elementInfo functions we get the controlled vocabulary terms for our field and field elements:
+The code above is how the field tells Drupal and Tripal how to find and filter the records that this field corresponds to.  First, we retrieve the field alias and operators:and as with the load and elementInfo functions we get the controlled vocabulary terms for our field and field elements:
 
 
 .. code-block:: php

+ 1 - 1
docs/dev_guide/custom_field/select_vocab_terms.rst

@@ -4,7 +4,7 @@ Selecting Vocabulary Terms
 Ontologies: what and why?
 -------------------------
 
-Tripal 3 requires all bundles and fields to be associated with a Controlled Vocabulary (CV). CVs are dictionaries of defined terms (CV terms) that make data machine-accessible, ensuring uniform terms are used across experiments, organisms and websites. Without CVterms, our scientific knowledge might be split by "dialects". Plant biologists might study temperature stress, while animal biologists study heat shock. Each group might benefit from the knowledge of the other, but they use a different vocabulary to describe the same thing, creating challenges for data discovery and exchange. CV terms make this easier not just for people, but especially for machines. Ontologies take this a step further. Where CVs are controlled lists of CVterms, ontologies are a controlled language, that include heirarchical relationships of terms.
+Tripal 3 requires all bundles and fields to be associated with a Controlled Vocabulary (CV). CVs are dictionaries of defined terms (CV terms) that make data machine-accessible, ensuring uniform terms are used across experiments, organisms and websites. Without CVterms, our scientific knowledge might be split by "dialects". Plant biologists might study temperature stress, while animal biologists study heat shock. Each group might benefit from the knowledge of the other, but they use a different vocabulary to describe the same thing, creating challenges for data discovery and exchange. CV terms make this easier not just for people, but especially for machines. Ontologies take this a step further. Where CVs are controlled lists of CVterms, ontologies are a controlled language, that include hierarchical relationships of terms.
 
 Tripal leverages vocabularies to make use of the `Semantic Web <https://en.wikipedia.org/wiki/Semantic_Web>`_. Every bundle and field defined in Tripal will be associated with a CVterm. Therefore, it is important to find community developed terms.  The `EMBL EBI Ontology Lookup Service <http://www.ebi.ac.uk/ols/index>`_ provides an easy location to search for and identify terms.  When choosing terms for new Bundles and Fields, think carefully about the terms you will use to describe your objects. Selecting the proper CV term that best describes the data may be the most challenging part of creating custom Bundles and Fields!
 

+ 1 - 1
docs/dev_guide/data_structures.rst

@@ -9,7 +9,7 @@ This page explains the relationships between Entity types, Bundles (content type
 * Entity Type:  despite the confusing name, an entity type is simply a group of bundles that are somehow related.  Drupal provides a "Node" Entity type that includes the Page and Article bundles.  All of the Tripal bundles (content types) belong to the TripalEntity Entity type.
 
 
-The following figure describes the heirarchical relationship between Drupal Entity types (e.g. Node) in comparison with TripalEntity entity types (e.g. Chromosome, Germplasm, etc.).
+The following figure describes the hierarchical relationship between Drupal Entity types (e.g. Node) in comparison with TripalEntity entity types (e.g. Chromosome, Germplasm, etc.).
 
 
 .. figure:: /_images/dev_guide/data_structures/Terminology-Diagram.png

+ 1 - 1
docs/dev_guide/introduction.rst

@@ -24,7 +24,7 @@ To use Chado for data storage:
 * Knowledge of Chado and relationships between tables (at least tables where data of interest is stored).
 * An idea how data is stored in Chado (or a willingness to ask questions)
 
-Things that will make your Tripal development experience postive, fun and rewarding:
+Things that will make your Tripal development experience positive, fun and rewarding:
 
 * A desire to write code that can be re-used and shared by other groups
 * A desire to share your work with others to support other the Tripal community members.

+ 1 - 1
docs/user_guide/bulk_loader.rst

@@ -316,7 +316,7 @@ Once complete, return to the search form, find a *Fragaria* species that has bee
 Sharing Your Templates with Others
 ----------------------------------
 
-Now that our template for loading organisms with NCBI Taxonomy IDs is completed we can share our template loader with anyone else that has a Tripal-based site.  To do this we simply export the template in text format, place it in a text file or directly in an email and send to a collaborator for import into their site.  To do this, navigate to **Tripal → Chado Data Loaders → Buik Loader** and click the **Tempalate** tab at the top.  Here we find a table of all the tempaltes we have created.  We should see our template named **NCBI Taxonomy Importer** (taxid, genus, species).  In the far right colum is a link to export that template.  Licking that link will redirect you to a page where the template is provided in a serialized PHP array.
+Now that our template for loading organisms with NCBI Taxonomy IDs is completed we can share our template loader with anyone else that has a Tripal-based site.  To do this we simply export the template in text format, place it in a text file or directly in an email and send to a collaborator for import into their site.  To do this, navigate to **Tripal → Chado Data Loaders → Buik Loader** and click the **Tempalate** tab at the top.  Here we find a table of all the templates we have created.  We should see our template named **NCBI Taxonomy Importer** (taxid, genus, species).  In the far right colum is a link to export that template.  Licking that link will redirect you to a page where the template is provided in a serialized PHP array.
 
 .. image:: ./bulk_loader.13.png
 

+ 2 - 2
docs/user_guide/content_types/configuring_page_display.rst

@@ -1,6 +1,6 @@
 Configuring Page Layout
 =======================
-This is one of the many new exciting features of Tripal v3. Integration with Drupal Fields has gone to a whole new level. Site builders have unprecendented control over the display of each piece of data through the administrative user interface. Previously, site builders were required to edit PHP template files to change the order, grouping or wording of content.
+This is one of the many new exciting features of Tripal v3. Integration with Drupal Fields has gone to a whole new level. Site builders have unprecedented control over the display of each piece of data through the administrative user interface. Previously, site builders were required to edit PHP template files to change the order, grouping or wording of content.
 
 You can configure the display of a given Tripal Content Type by navigating to **Structure → Tripal Content Types** and then selecting the **Manage Display** link beside the content type you would like to configure.
 
@@ -15,7 +15,7 @@ The Manage Display User Interface lists each Drupal Field in the order they will
 Rearranging Fields
 ------------------
 
-To rearrange the fields within a Tripal pane, simply drag them into the order you would like them. For example, the description is currently within the Summary table --it makes much more sense for it to be below the table but still within the summary. To do this, simply drag the description field to the bottom of the summary table and then move it in one level as shown in the following screenshot. Then click the **Save** button at the botton to save the changes.
+To rearrange the fields within a Tripal pane, simply drag them into the order you would like them. For example, the description is currently within the Summary table --it makes much more sense for it to be below the table but still within the summary. To do this, simply drag the description field to the bottom of the summary table and then move it in one level as shown in the following screenshot. Then click the **Save** button at the bottom to save the changes.
 
 .. image:: configuring_page_display.3.rearrange.png
 

+ 1 - 1
docs/user_guide/content_types/field_loading.rst

@@ -23,4 +23,4 @@ Depending on the number of fields for your content type and the amount of data t
 
 .. note::
  
-  You can control AJAX loading and hiding of empty fields differently for each conent type.
+  You can control AJAX loading and hiding of empty fields differently for each content type.

+ 1 - 1
docs/user_guide/install_tripal/drupal_home.rst

@@ -1,6 +1,6 @@
 DRUPAL_HOME Variable
 ====================
-An important convention in this document is the use of the ``$DRUPAL_HOME`` environment variable.  If you are new to UNIX/Linux you can learn about environment variables `here <https://www.tutorialspoint.com/unix/unix-environment.htm>`_.  Drupal is a necessary depenency of Tripal.  The setup and installation sections describe how to install Drupal.  If you follow the instructions exactly as described in this User's Guide you will install Drupal into ``/var/www/html``. However, some may desire to install Drupal elsewhere.  To ensure that all command-line examples in this guide can be cut-and-pasted you **must** set the ``$DRUPAL_HOME`` variable.  You can set the variable in the following way:
+An important convention in this document is the use of the ``$DRUPAL_HOME`` environment variable.  If you are new to UNIX/Linux you can learn about environment variables `here <https://www.tutorialspoint.com/unix/unix-environment.htm>`_.  Drupal is a necessary dependency of Tripal.  The setup and installation sections describe how to install Drupal.  If you follow the instructions exactly as described in this User's Guide you will install Drupal into ``/var/www/html``. However, some may desire to install Drupal elsewhere.  To ensure that all command-line examples in this guide can be cut-and-pasted you **must** set the ``$DRUPAL_HOME`` variable.  You can set the variable in the following way:
 
   .. code-block:: bash
 

+ 1 - 1
docs/user_guide/install_tripal/server_setup.rst

@@ -6,7 +6,7 @@ Before installation of Tripal, a web server must be configured and ready, and Tr
 1. A UNIX-based server (e.g. Ubuntu Linux or CentOS are the most popularly used).
 2. Web server software. The `Apache web server <https://httpd.apache.org/>`_ is most commonly used.
 3. `PHP <http://php.net/>`_ version 5.6 or higher (the most recent version is recommended).
-4. `PostgreSQL <https://www.postgresql.org/>`_ 9.3 or higher
+4. `PostgreSQL <https://www.postgresql.org/>`_ 9.3 or higher (9.5 required for Chado 1.2 to 1.3 upgrade)
 5. `Drush <http://www.drush.org/en/master/>`_ 7 or higher
 6. `Drupal <https://www.drupal.org/>`_ 7.
 

+ 1 - 1
docs/user_guide/job_management.rst

@@ -6,7 +6,7 @@ Job Management (Tripal Daemon)
   Remember you must set the $DRUPAL_HOME environment variable to cut-and-paste the commands below. See see :doc:`./install_tripal/drupal_home`
 
 
-The Tripal Daemon module is meant to provide a simple means of creating a robust command-line-driven, fully bootstrapped PHP Daemon. It uses the PHP-Daemon (https://github.com/shaneharter/PHP-Daemon) Library to create the Daemon (via the Libraries API) in order to not re-invent the wheel. It allows you to execute Jobs submitted to Tripal without using cron.  It provides a faster user experience for running jobs.  Prior to Tripal v3, the Tripal Daemon module was an extension module. It was integrated into the core Tripal pacakge.
+The Tripal Daemon module is meant to provide a simple means of creating a robust command-line-driven, fully bootstrapped PHP Daemon. It uses the PHP-Daemon (https://github.com/shaneharter/PHP-Daemon) Library to create the Daemon (via the Libraries API) in order to not re-invent the wheel. It allows you to execute Jobs submitted to Tripal without using cron.  It provides a faster user experience for running jobs.  Prior to Tripal v3, the Tripal Daemon module was an extension module. It was integrated into the core Tripal package.
 
 Features
 --------

+ 1 - 1
docs/user_guide/searching/search_api.rst

@@ -32,7 +32,7 @@ This tutorial covers using a basic Drupal database storage backend for your sear
 .. figure:: ./search_api.2.png
 
 
-Before proceeding, consider deleting the "Default node index". We don't need it.  Next, click the **Add Server link**.  We are configuring a basic drupal database seach server we do not need to install any third-part software or set-up an external server. Instead, fill out the configuration form to tell the Search API to use its own database to store the search index.  Give this server the name "Drupal Database" and select "Database service" from the **Service Class** drop down.  In the **Database Service** section, select  "Search on parts of a word." If the search is slow due to this feature, then it is an indicator that your site should use a different service class (ie: Elastic Search or Apache Solr). Click "Create Server" to finish configuring the Search backend.
+Before proceeding, consider deleting the "Default node index". We don't need it.  Next, click the **Add Server link**.  We are configuring a basic drupal database search server we do not need to install any third-part software or set-up an external server. Instead, fill out the configuration form to tell the Search API to use its own database to store the search index.  Give this server the name "Drupal Database" and select "Database service" from the **Service Class** drop down.  In the **Database Service** section, select  "Search on parts of a word." If the search is slow due to this feature, then it is an indicator that your site should use a different service class (ie: Elastic Search or Apache Solr). Click "Create Server" to finish configuring the Search backend.
 
 
 .. figure:: ./search_api.3.png

+ 129 - 110
legacy/tripal_phylogeny/theme/js/tripal_phylogeny.js

@@ -2,129 +2,148 @@
 
 (function ($) {
 
-  var height = 0; // will be dynamically sized
+  "use strict";
 
-  $(document).ready( function () {
+  // Will be dynamically sized.
+  var height = 0;
 
-    // Callback function to determine node size.
-    var nodeSize = function(d) {
-      var size;
-      if (d.cvterm_name == "phylo_root") {
-        size = treeOptions['root_node_size']; 
-      }
-      if (d.cvterm_name == "phylo_interior") {
-        size = treeOptions['interior_node_size']; 
-      }
-      if (d.cvterm_name == "phylo_leaf") {
-        size = treeOptions['leaf_node_size']; 
-      }
-      return size;
+  // Store our function as a property of Drupal.behaviors.
+  Drupal.behaviors.TripalPhylotree = {
+    attach: function (context, settings) {
+
+      // Retrieve the data for this tree.
+      var data_url = Drupal.settings.tripal_chado.phylotree_url;
+      $.getJSON(data_url, function(treeData) {
+        phylogeny_display_data(treeData);
+        $('.phylogram-ajax-loader').hide();
+      });
     }
+  }
 
-    // Callback function to determine the node color.
-    var organismColor = function(d) {
-      var color = null;
-      if (d.genus) {
-        color = organismColors[d.genus + ' ' + d.species];
-      }
-      if (color) { 
-        return color; 
-      }
-      else { 
-        return 'grey'; 
-      }
-    };
+  // Callback function to determine node size.
+  var phylogeny_node_size = function(d) {
+    var size;
+    var tree_options = Drupal.settings.tripal_chado.tree_options;
+    if (d.cvterm_name == "phylo_root") {
+      size = tree_options['root_node_size'];
+    }
+    if (d.cvterm_name == "phylo_interior") {
+      size = tree_options['interior_node_size'];
+    }
+    if (d.cvterm_name == "phylo_leaf") {
+      size = tree_options['leaf_node_size'];
+    }
+    return size;
+  }
 
-    // Callback for mouseover event on graph node d.
-    var nodeMouseOver = function(d) {
-      var el = $(this);
-      el.attr('cursor', 'pointer');
-      var circle = el.find('circle');
-      // highlight in yellow no matter if leaf or interior node
-      circle.attr('fill', 'yellow');
-      if(!d.children) {
-        // only leaf nodes have descriptive text
-        var txt = el.find('text');
-        txt.attr('font-weight', 'bold');
-      }
-    };
-    
-    // Callback for mouseout event on graph node d.
-    var nodeMouseOut = function(d) {
-      var el = $(this);
-      el.attr('cursor', 'default');
-      var circle = el.find('circle');
-      if(!d.children) {
-        // restore the color based on organism id for leaf nodes
-        circle.attr('fill', organismColor(d));
-        var txt = el.find('text');
-        txt.attr('font-weight', 'normal');
+  // Callback function to determine the node color.
+  var phylogeny_organism_color = function(d) {
+    var organism_color = Drupal.settings.tripal_chado.org_colors;
+    var color = null;
+
+    if (d.fo_genus) {
+      color = organism_color[d.fo_organism_id];
+    }
+    if (color) {
+      return color;
+    }
+    else {
+      return 'grey';
+    }
+  };
+
+  // Callback for mouseover event on graph node d.
+  var phylogeny_node_mouse_over = function(d) {
+    var el = $(this);
+    el.attr('cursor', 'pointer');
+    var circle = el.find('circle');
+    // highlight in yellow no matter if leaf or interior node
+    circle.attr('fill', 'yellow');
+    if(!d.children) {
+      // only leaf nodes have descriptive text
+      var txt = el.find('text');
+      txt.attr('font-weight', 'bold');
+    }
+  };
+
+  // Callback for mouseout event on graph node d.
+  var phylogeny_node_mouse_out = function(d) {
+    var el = $(this);
+    el.attr('cursor', 'default');
+    var circle = el.find('circle');
+    if(!d.children) {
+      // restore the color based on organism id for leaf nodes
+      circle.attr('fill', phylogeny_organism_color(d));
+      var txt = el.find('text');
+      txt.attr('font-weight', 'normal');
+    }
+    else {
+      // restore interior nodes to white
+      circle.attr('fill', 'white');
+    }
+  };
+
+  // Callback for mousedown/click event on graph node d.
+  var phylogeny_node_mouse_down = function(d) {
+    var el = $(this);
+    var title = (! d.children ) ? d.name : 'interior node ' + d.phylonode_id;
+
+    if(d.children) {
+      // interior node
+      if(d.phylonode_id) {
       }
       else {
-        // restore interior nodes to white
-        circle.attr('fill', 'white');
+        // this shouldn't happen but ok
       }
-    };
-    
-    // Callback for mousedown/click event on graph node d.
-    var nodeMouseDown = function(d) {
-      var el = $(this);
-      var title = (! d.children ) ? d.name : 'interior node ' + d.phylonode_id;
+    }
+    else {
+      if(d.feature_eid) {
+        window.location.href = baseurl + '/bio_data/' + d.feature_eid;
 
-      if(d.children) {
-        // interior node
-        if(d.phylonode_id) {
-        }
-        else {
-          // this shouldn't happen but ok
-        }
+        return;
       }
-      else {
-        // If this node is not associated with a feature but it has an 
-        // organism node then this is a taxonomic node and we want to
-        // link it to the organism page.
-        if (!d.feature_id && d.organism_node_id) {
-          window.location.replace(baseurl + '/node/' + d.organism_node_id);
-        }
-        // leaf node
+      // If this node is not associated with a feature but it has an
+      // organism node then this is a taxonomic node and we want to
+      // link it to the organism page.
+      if (!d.feature_id && d.organism_nid) {
+        window.location.replace(baseurl + '/node/' + d.organism_nid);
+      }
+      if (!d.feature_id && d.organism_eid) {
+        window.location.replace(baseurl + '/bio_data/' + d.organism_eid);
       }
-    };
+      // leaf node
+    }
+  };
 
-    // AJAX function for retrieving the tree data.
-    $.getJSON(phylotreeDataURL, function(treeData) {
-      displayData(treeData);
-      $('.phylogram-ajax-loader').hide();
+  // Creates the tree using the d3.phylogram.js library.
+  function phylogeny_display_data(treeData) {
+    var height = phylogeny_graph_height(treeData);
+    var tree_options = Drupal.settings.tripal_chado.tree_options;
+    d3.phylogram.build('#phylogram', treeData, {
+      'width' : tree_options['phylogram_width'],
+      'height' : height,
+      'fill' : phylogeny_organism_color,
+      'size' : phylogeny_node_size,
+      'nodeMouseOver' : phylogeny_node_mouse_over,
+      'nodeMouseOut' : phylogeny_node_mouse_out,
+      'nodeMouseDown' : phylogeny_node_mouse_down,
+      'skipTicks' : tree_options['skipTicks']
     });
+  }
 
-    // Creates the tree using the d3.phylogram.js library.
-    function displayData(treeData) {
-      height = graphHeight(treeData);
-      d3.phylogram.build('#phylogram', treeData, {
-        'width' : treeOptions['phylogram_width'],
-        'height' : height,
-        'fill' : organismColor,
-        'size' : nodeSize,
-        'nodeMouseOver' : nodeMouseOver,
-        'nodeMouseOut' : nodeMouseOut,
-        'nodeMouseDown' : nodeMouseDown,
-        'skipTicks' : treeOptions['skipTicks']
-      });
-    }
-
-    /* graphHeight() generate graph height based on leaf nodes */
-    function graphHeight(data) {
-      function countLeafNodes(node) {
-        if(! node.children) {
-          return 1;
-        }
-        var ct = 0;
-        node.children.forEach( function(child) {
-          ct+= countLeafNodes(child);
-        });
-        return ct;
+  /* graphHeight() generate graph height based on leaf nodes */
+  function phylogeny_graph_height(data) {
+    function count_leaf_nodes(node) {
+      if(! node.children) {
+        return 1;
       }
-      var leafNodeCt = countLeafNodes(data);
-      return 22 * leafNodeCt;
+      var ct = 0;
+      node.children.forEach( function(child) {
+        ct+= count_leaf_nodes(child);
+      });
+      return ct;
     }
-  });
-})(jQuery);
+    var leafNodeCt = count_leaf_nodes(data);
+    return 22 * leafNodeCt;
+  }
+})(jQuery);

+ 4 - 4
tripal/tripal_views_query.inc

@@ -112,7 +112,7 @@ class tripal_views_query extends views_plugin_query {
       // For fields compatible with the Tripal storage API, the
       // incoming $field_name is a combination of the entity term ID,
       // followed by the field name and the the sub element string, with
-      // sub elements children separated by a comma.  For non Tripal 
+      // sub elements children separated by a period.  For non Tripal
       // storage API the $field_name is a combination of the table name
       // followed by the table column.  We have to handle both because
       // a TripalEntity can have both types attached.
@@ -121,8 +121,8 @@ class tripal_views_query extends views_plugin_query {
       if (count($elements) > 2) {
         $bundle_term = array_shift($elements);
         $field_name = array_shift($elements);
-        // put the sub elements back together into a string with a 
-        // comma delimeter.
+        $field = field_info_field($field_name);
+        // put the sub elements back together into a string with a comma.
         $element_name = implode(',', $elements);
       }
       if (count($elements) == 2) {
@@ -146,7 +146,7 @@ class tripal_views_query extends views_plugin_query {
         // Construct the field term.
         $field_term = $instance['settings']['term_vocabulary'] . ':' . $instance['settings']['term_accession'];
 
-        // Let's add add on the $field_term to the element_name and add the
+        // Let's add on the $field_term to the element_name and add the
         // query condition.
         if ($element_name) {
           $element_name = $field_term . ',' . $element_name;

+ 210 - 210
tripal_chado/chado_schema/default_schema-1.2-1.3-diff.sql

@@ -3010,12 +3010,12 @@ NOT have the specified term.';
 -- Name: analysis_cvterm_analysis_cvterm_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE analysis_cvterm_analysis_cvterm_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS analysis_cvterm_analysis_cvterm_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -3057,12 +3057,12 @@ accessions should set this field to false';
 -- Name: analysis_dbxref_analysis_dbxref_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE analysis_dbxref_analysis_dbxref_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS analysis_dbxref_analysis_dbxref_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -3095,12 +3095,12 @@ COMMENT ON TABLE analysis_pub IS 'Provenance. Linking table between analyses and
 -- Name: analysis_pub_analysis_pub_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE analysis_pub_analysis_pub_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS analysis_pub_analysis_pub_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 
@@ -3171,12 +3171,12 @@ important where rank is used to order these; starts from zero.';
 -- Name: analysis_relationship_analysis_relationship_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE analysis_relationship_analysis_relationship_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS analysis_relationship_analysis_relationship_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -3492,12 +3492,12 @@ relational schema, and is completely extensible.';
 -- Name: contactprop_contactprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE contactprop_contactprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS contactprop_contactprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -3589,12 +3589,12 @@ the combination of db_id, rank, and type_id. Multivalued property-value pairs mu
 -- Name: dbprop_dbprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE dbprop_dbprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS dbprop_dbprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: dbprop_dbprop_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -3747,12 +3747,12 @@ person or organization responsible for discovery or that can provide more inform
 -- Name: feature_contact_feature_contact_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE feature_contact_feature_contact_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS feature_contact_feature_contact_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: feature_contact_feature_contact_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -3920,12 +3920,12 @@ that can provide more information on a particular featuremap.';
 -- Name: featuremap_contact_featuremap_contact_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE featuremap_contact_featuremap_contact_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS featuremap_contact_featuremap_contact_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: featuremap_contact_featuremap_contact_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -3949,12 +3949,12 @@ CREATE TABLE IF NOT EXISTS featuremap_dbxref (
 -- Name: featuremap_dbxref_featuremap_dbxref_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE featuremap_dbxref_featuremap_dbxref_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS featuremap_dbxref_featuremap_dbxref_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: featuremap_dbxref_featuremap_dbxref_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -3984,12 +3984,12 @@ COMMENT ON TABLE featuremap_organism IS 'Links a featuremap to the organism(s) w
 -- Name: featuremap_organism_featuremap_organism_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE featuremap_organism_featuremap_organism_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS featuremap_organism_featuremap_organism_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: featuremap_organism_featuremap_organism_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4031,12 +4031,12 @@ relational schema, and is completely extensible.';
 -- Name: featuremapprop_featuremapprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE featuremapprop_featuremapprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS featuremapprop_featuremapprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -4081,12 +4081,12 @@ COMMENT ON TABLE featureposprop IS 'Property or attribute of a featurepos record
 -- Name: featureposprop_featureposprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE featureposprop_featureposprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS featureposprop_featureposprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: featureposprop_featureposprop_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4171,12 +4171,12 @@ COMMENT ON TABLE library_contact IS 'Links contact(s) with a library.  Used to i
 -- Name: library_contact_library_contact_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE library_contact_library_contact_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS library_contact_library_contact_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: library_contact_library_contact_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4231,12 +4231,12 @@ COMMENT ON TABLE library_expression IS 'Links a library to expression statements
 -- Name: library_expression_library_expression_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE library_expression_library_expression_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS library_expression_library_expression_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: library_expression_library_expression_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4268,12 +4268,12 @@ COMMENT ON TABLE library_expressionprop IS 'Attributes of a library_expression r
 -- Name: library_expressionprop_library_expressionprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE library_expressionprop_library_expressionprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS library_expressionprop_library_expressionprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: library_expressionprop_library_expressionprop_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4313,12 +4313,12 @@ COMMENT ON TABLE library_featureprop IS 'Attributes of a library_feature relatio
 -- Name: library_featureprop_library_featureprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE library_featureprop_library_featureprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS library_featureprop_library_featureprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: library_featureprop_library_featureprop_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4364,12 +4364,12 @@ COMMENT ON TABLE library_relationship IS 'Relationships between libraries.';
 -- Name: library_relationship_library_relationship_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE library_relationship_library_relationship_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS library_relationship_library_relationship_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -4400,12 +4400,12 @@ COMMENT ON TABLE library_relationship_pub IS 'Provenance of library_relationship
 -- Name: library_relationship_pub_library_relationship_pub_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE library_relationship_pub_library_relationship_pub_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS library_relationship_pub_library_relationship_pub_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: library_relationship_pub_library_relationship_pub_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4518,12 +4518,12 @@ COMMENT ON TABLE nd_experiment_analysis IS 'An analysis that is used in an exper
 -- Name: nd_experiment_analysis_nd_experiment_analysis_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE nd_experiment_analysis_nd_experiment_analysis_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS nd_experiment_analysis_nd_experiment_analysis_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: nd_experiment_analysis_nd_experiment_analysis_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4774,12 +4774,12 @@ the default 0 value should be used';
 -- Name: organism_cvterm_organism_cvterm_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE organism_cvterm_organism_cvterm_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS organism_cvterm_organism_cvterm_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: organism_cvterm_organism_cvterm_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4843,12 +4843,12 @@ the default 0 value should be used';
 -- Name: organism_cvtermprop_organism_cvtermprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE organism_cvtermprop_organism_cvtermprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS organism_cvtermprop_organism_cvtermprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: organism_cvtermprop_organism_cvtermprop_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4893,12 +4893,12 @@ COMMENT ON TABLE organism_pub IS 'Attribution for organism.';
 -- Name: organism_pub_organism_pub_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE organism_pub_organism_pub_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS organism_pub_organism_pub_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: organism_pub_organism_pub_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4933,12 +4933,12 @@ relatinoships should be housed in the phylogeny tables.';
 -- Name: organism_relationship_organism_relationship_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE organism_relationship_organism_relationship_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS organism_relationship_organism_relationship_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: organism_relationship_organism_relationship_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -4978,12 +4978,12 @@ COMMENT ON TABLE organismprop_pub IS 'Attribution for organismprop.';
 -- Name: organismprop_pub_organismprop_pub_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE organismprop_pub_organismprop_pub_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS organismprop_pub_organismprop_pub_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: organismprop_pub_organismprop_pub_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -5077,12 +5077,12 @@ COMMENT ON TABLE phenotypeprop IS 'A phenotype can have any number of slot-value
 -- Name: phenotypeprop_phenotypeprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE phenotypeprop_phenotypeprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS phenotypeprop_phenotypeprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: phenotypeprop_phenotypeprop_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -5233,12 +5233,12 @@ default 0 value should be used';
 -- Name: phylotreeprop_phylotreeprop_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE phylotreeprop_phylotreeprop_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS phylotreeprop_phylotreeprop_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -5287,12 +5287,12 @@ The rank column can be used to specify a simple ordering in which analyses were
 -- Name: project_analysis_project_analysis_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE project_analysis_project_analysis_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS project_analysis_project_analysis_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 
 --
@@ -5347,12 +5347,12 @@ COMMENT ON COLUMN project_dbxref.is_current IS 'The is_current boolean indicates
 -- Name: project_dbxref_project_dbxref_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE project_dbxref_project_dbxref_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS project_dbxref_project_dbxref_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: project_dbxref_project_dbxref_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -5383,12 +5383,12 @@ COMMENT ON TABLE project_feature IS 'This table is intended associate records in
 -- Name: project_feature_project_feature_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE project_feature_project_feature_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS project_feature_project_feature_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: project_feature_project_feature_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -5453,12 +5453,12 @@ COMMENT ON TABLE project_stock IS 'This table is intended associate records in t
 -- Name: project_stock_project_stock_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE project_stock_project_stock_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS project_stock_project_stock_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 --
 -- Name: projectprop; Type: TABLE; Schema: public; Owner: chado; Tablespace: 
 --
@@ -5537,12 +5537,12 @@ COMMENT ON TABLE pubauthor_contact IS 'An author on a publication may have a cor
 -- Name: pubauthor_contact_pubauthor_contact_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE pubauthor_contact_pubauthor_contact_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS pubauthor_contact_pubauthor_contact_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: pubauthor_contact_pubauthor_contact_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -5660,12 +5660,12 @@ COMMENT ON TABLE stock_feature IS 'Links a stock to a feature.';
 -- Name: stock_feature_stock_feature_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE stock_feature_stock_feature_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS stock_feature_stock_feature_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: stock_feature_stock_feature_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: chado
@@ -5697,12 +5697,12 @@ COMMENT ON TABLE stock_featuremap IS 'Links a featuremap to a stock.';
 -- Name: stock_featuremap_stock_featuremap_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE stock_featuremap_stock_featuremap_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS stock_featuremap_stock_featuremap_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: stock_genotype; Type: TABLE; Schema: public; Owner: chado; Tablespace: 
@@ -5735,12 +5735,12 @@ COMMENT ON TABLE stock_library IS 'Links a stock with a library.';
 -- Name: stock_library_stock_library_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE stock_library_stock_library_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS stock_library_stock_library_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: stock_pub; Type: TABLE; Schema: public; Owner: chado; Tablespace: 
@@ -5815,12 +5815,12 @@ db_id record';
 -- Name: stockcollection_db_stockcollection_db_id_seq; Type: SEQUENCE; Schema: public; Owner: chado
 --
 
----CREATE SEQUENCE stockcollection_db_stockcollection_db_id_seq
----    START WITH 1
----    INCREMENT BY 1
----    NO MINVALUE
----    NO MAXVALUE
----    CACHE 1;
+CREATE SEQUENCE IF NOT EXISTS stockcollection_db_stockcollection_db_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
 
 --
 -- Name: stockcollection_stock; Type: TABLE; Schema: public; Owner: chado; Tablespace: 

+ 2 - 2
tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence.inc

@@ -93,7 +93,7 @@ class data__protein_sequence extends ChadoField {
       WHERE
         FR.object_id = :feature_id and
         CVT.name = 'polypeptide' and
-        RCVT.name = 'derives_from'
+        RCVT.name  IN ('derives_from', 'part_of')
       ORDER BY FR.rank ASC
     ";
     $proteins = chado_query($sql, [':feature_id' => $feature->feature_id]);
@@ -108,4 +108,4 @@ class data__protein_sequence extends ChadoField {
       $num_seqs++;
     }
   }
-}
+}

+ 1 - 1
tripal_chado/includes/TripalFields/so__transcript/so__transcript_formatter.inc

@@ -32,7 +32,7 @@ class so__transcript_formatter extends ChadoFieldFormatter {
       $loc = $transcript['SO:0000735'];
       $type = $transcript['rdfs:type'];
 
-      // Add a link i there is an entity.
+      // Add a link if there is an entity.
       if (array_key_exists('entity', $item['value']) and $item['value']['entity']) {
         list($entity_type, $entity_id) = explode(':', $item['value']['entity']);
         $feature_name = l($feature_name, "bio_data/" . $entity_id, ['attributes' => ['target' => "_blank"]]);

+ 105 - 18
tripal_chado/includes/TripalImporter/TaxonomyImporter.inc

@@ -130,6 +130,30 @@ class TaxonomyImporter extends TripalImporter {
         already exist on this site.  This loader will also construct
         the taxonomic tree for the species loaded.'),
     ];
+
+    $form['ncbi_api_key'] = [
+      '#type' => 'textfield',
+      '#title' => t('(Optional) NCBI API key:'),
+      '#description' => t('Tripal imports Taxonomy information using NCBI\'s ')
+        . l('EUtils API', 'https://www.ncbi.nlm.nih.gov/books/NBK25500/')
+        . t(', which limits users and programs to a maximum of 3 requests per second without an API key. '
+          . 'However, NCBI allows users and programs to an increased maximum of 10 requests per second if '
+          . 'they provide a valid API key. This is particularly useful in speeding up large taxonomy imports. '
+          . 'For more information on NCBI API keys, please ')
+        . l('see here', 'https://www.ncbi.nlm.nih.gov/books/NBK25497/#chapter2.Coming_in_December_2018_API_Key', array(
+        'attributes' => array(
+          'target' => 'blank',
+        ),
+      )) . '.',
+      '#default_value' => variable_get('tripal_taxon_importer_ncbi_api_key', NULL),
+      '#ajax' => array(
+        'callback' => 'tripal_taxon_importer_set_ncbi_api_key',
+        'wrapper' => 'ncbi_api_key',
+      ),
+      '#prefix' => '<div id="ncbi_api_key">',
+      '#suffix' => '</div>',
+    ];
+
     $form['taxonomy_ids'] = [
       '#type' => 'textarea',
       '#title' => 'Taxonomy ID',
@@ -147,7 +171,7 @@ class TaxonomyImporter extends TripalImporter {
         taxonomic details.  If the importer is able to match the
         genus and species with NCBI the species details will be imported,
         and a page containing the taxonomic tree will be created.'),
-      '#default value' => 1,
+      '#default_value' => 1,
     ];
     return $form;
   }
@@ -242,10 +266,26 @@ class TaxonomyImporter extends TripalImporter {
     // If the user wants to import new taxonomy IDs then do that.
     if ($taxonomy_ids) {
       $this->logMessage('Importing Taxonomy IDs...');
+      $api_key = variable_get('tripal_taxon_importer_ncbi_api_key', NULL);
+      $sleep_time = 333334;
+      if (!empty($api_key)) {
+        $sleep_time = 100000;
+      }
+
       foreach ($tax_ids as $tax_id) {
+        $start = microtime(TRUE);
         $tax_id = trim($tax_id);
-        $this->importRecord($tax_id);
-        $this->addItemsHandled(1);
+        $result = $this->importRecord($tax_id);
+
+        // Only addItemsHandled if the importRecord was a success.
+        if ($result) {
+          $this->addItemsHandled(1);
+        }
+
+        $remaining_sleep = $sleep_time - ((int) (1e6 * (microtime(TRUE) - $start)));
+        if ($remaining_sleep > 0) {
+          usleep($remaining_sleep);
+        }
       }
     }
 
@@ -463,9 +503,12 @@ class TaxonomyImporter extends TripalImporter {
    */
   private function updateExisting() {
 
-    $i = 0;
-
     $total = count($this->all_orgs);
+    $api_key = variable_get('tripal_taxon_importer_ncbi_api_key', NULL);
+    $sleep_time = 333334;
+    if (!empty($api_key)) {
+      $sleep_time = 100000;
+    }
 
     foreach ($this->all_orgs as $organism) {
       // If the organism record is marked as new then let's skip it because
@@ -477,13 +520,18 @@ class TaxonomyImporter extends TripalImporter {
       // TODO: we should check if the organism already has a taxonomy ID.
       // if so we should use that instead of the scientific name.
 
+      $start = microtime(TRUE);
       // Build the query string to get the information about this species.
       $sci_name = chado_get_organism_scientific_name($organism);
       $sci_name = urlencode($sci_name);
-      $search_url = "http://www.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?" .
+      $search_url = "https://www.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?" .
         "db=taxonomy" .
         "&term=$sci_name";
 
+      if (!empty($api_key)) {
+        $search_url .= "&api_key=" . $api_key;
+      }
+
       // Get the search response from NCBI.
       $rfh = fopen($search_url, "r");
       $xml_text = '';
@@ -498,22 +546,30 @@ class TaxonomyImporter extends TripalImporter {
       }
       fclose($rfh);
 
+      $remaining_sleep = $sleep_time - ((int) (1e6 * (microtime(TRUE) - $start)));
+      if ($remaining_sleep > 0) {
+        usleep($remaining_sleep);
+      }
+
       // Parse the XML to get the taxonomy ID
+      $result = FALSE;
+      $start = microtime(TRUE);
       $xml = new SimpleXMLElement($xml_text);
       if ($xml) {
         $taxid = (string) $xml->IdList->Id;
         if ($taxid) {
-          $this->importRecord($taxid, $organism);
+          $result = $this->importRecord($taxid, $organism);
         }
       }
-      $this->addItemsHandled(1);
 
-      // NCBI limits requests to 3/second.
-      if ($i % 3 == 0) {
-        sleep(1);
+      if ($result) {
+        $this->addItemsHandled(1);
       }
-      $i++;
 
+      $remaining_sleep = $sleep_time - ((int) (1e6 * (microtime(TRUE) - $start)));
+      if ($remaining_sleep > 0) {
+        usleep($remaining_sleep);
+      }
     }
   }
 
@@ -675,19 +731,28 @@ class TaxonomyImporter extends TripalImporter {
     ]);
 
     // Get the details for this taxonomy.
-    $fetch_url = "http://www.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?" .
+    $fetch_url = "https://www.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?" .
       "db=taxonomy" .
       "&id=$taxid";
 
+    $api_key = variable_get('tripal_taxon_importer_ncbi_api_key', NULL);
+    if (!empty($api_key)) {
+      $fetch_url .= "&api_key=" . $api_key;
+    }
+
     // Get the search response from NCBI.
+    $xml = FALSE;
     $rfh = fopen($fetch_url, "r");
-    $xml_text = '';
-    while (!feof($rfh)) {
-      $xml_text .= fread($rfh, 255);
+    if ($rfh) {
+      $xml_text = '';
+      while (!feof($rfh)) {
+        $xml_text .= fread($rfh, 255);
+      }
+      fclose($rfh);
+
+      $xml = new SimpleXMLElement($xml_text);
     }
-    fclose($rfh);
 
-    $xml = new SimpleXMLElement($xml_text);
     if ($xml) {
       $taxon = $xml->Taxon;
 
@@ -817,7 +882,9 @@ class TaxonomyImporter extends TripalImporter {
 
       // Set the indecies for the tree.
       chado_assign_phylogeny_tree_indices($this->tree);
+      return TRUE;
     }
+    return FALSE;
   }
 
   /**
@@ -941,3 +1008,23 @@ class TaxonomyImporter extends TripalImporter {
     }
   }
 }
+
+/**
+ * Ajax callback for the TaxonomyImporter::form() function.
+ *
+ * It is called when the user makes a change to the NCBI API key field and then
+ * moves their cursor out of the field.
+ *
+ * @param $form
+ *   The new form element.
+ * @param $form_state
+ *   The state of the new form element.
+ *
+ * @return array
+ *   The new api key field.
+ */
+function tripal_taxon_importer_set_ncbi_api_key($form, $form_state) {
+  variable_set('tripal_taxon_importer_ncbi_api_key', check_plain($form_state['values']['ncbi_api_key']));
+  drupal_set_message('NCBI API key has been saved successfully!');
+  return $form['ncbi_api_key'];
+}

+ 1 - 49
tripal_chado/includes/tripal_chado.install.inc

@@ -58,7 +58,7 @@ function tripal_chado_load_form($form, $form_state) {
         'stockcollection_db',
       ]);
       $items = [
-        'PostgreSQL version 9.1 is required to perform this upgrade. If your Tripal
+        'PostgreSQL version 9.5 is required to perform this upgrade. If your Tripal
          site uses an older version please upgrade before proceeding.',
         'A major change between Chado v1.2 and v1.3 is that primary and foreign
          keys were upgraded from integers to big integers. If your site has custom
@@ -501,54 +501,6 @@ function tripal_chado_upgrade_chado_1_2_to_1_3_pre_alter() {
 
     }
   }
-  // Now create the sequences if they don't already exist.
-  $sequences = [
-    'analysis_cvterm_analysis_cvterm_id_seq',
-    'analysis_dbxref_analysis_dbxref_id_seq',
-    'analysis_pub_analysis_pub_id_seq',
-    'analysis_relationship_analysis_relationship_id_seq',
-    'contactprop_contactprop_id_seq',
-    'dbprop_dbprop_id_seq',
-    'feature_contact_feature_contact_id_seq',
-    'featuremap_contact_featuremap_contact_id_seq',
-    'featuremap_dbxref_featuremap_dbxref_id_seq',
-    'featuremap_organism_featuremap_organism_id_seq',
-    'featuremapprop_featuremapprop_id_seq',
-    'featureposprop_featureposprop_id_seq',
-    'library_contact_library_contact_id_seq',
-    'library_expression_library_expression_id_seq',
-    'library_expressionprop_library_expressionprop_id_seq',
-    'library_featureprop_library_featureprop_id_seq',
-    'library_relationship_library_relationship_id_seq',
-    'library_relationship_pub_library_relationship_pub_id_seq',
-    'nd_experiment_analysis_nd_experiment_analysis_id_seq',
-    'organism_cvterm_organism_cvterm_id_seq',
-    'organism_cvtermprop_organism_cvtermprop_id_seq',
-    'organism_pub_organism_pub_id_seq',
-    'organism_relationship_organism_relationship_id_seq',
-    'organismprop_pub_organismprop_pub_id_seq',
-    'phenotypeprop_phenotypeprop_id_seq',
-    'phylotreeprop_phylotreeprop_id_seq',
-    'project_analysis_project_analysis_id_seq',
-    'project_dbxref_project_dbxref_id_seq',
-    'project_feature_project_feature_id_seq',
-    'project_stock_project_stock_id_seq',
-    'pubauthor_contact_pubauthor_contact_id_seq',
-    'stock_feature_stock_feature_id_seq',
-    'stock_featuremap_stock_featuremap_id_seq',
-    'stock_library_stock_library_id_seq',
-    'stockcollection_db_stockcollection_db_id_seq',
-  ];
-  foreach ($sequences as $sequence) {
-
-    // Now add in the sequences if they don't already exist. There is no
-    // PostgreSQL 'CREATE SEQUENCE IF NOT EXIST' so we're forced to do it here
-    // and these create statements were removed from the diff upgrade file.
-    if (!chado_sequence_exists($sequence)) {
-      $sql = "CREATE SEQUENCE {" . $sequence . "} START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1";
-      chado_query($sql);
-    }
-  }
 }
 
 /**

+ 50 - 33
tripal_chado/includes/tripal_chado.phylotree.inc

@@ -4,7 +4,8 @@
  *
  * @param $phylotree
  */
-function tripal_phylogeny_prepare_tree_viewer($phylotree) {
+function tripal_phylogeny_prepare_tree_viewer($phylotree)
+{
 
   // If the phylotree is not provided then just return;
   if (!$phylotree) {
@@ -59,6 +60,7 @@ function tripal_phylogeny_prepare_tree_viewer($phylotree) {
         'interior_node_size' => variable_get('tripal_phylogeny_default_interior_node_size', 1),
         'leaf_node_size' => variable_get('tripal_phylogeny_default_leaf_node_size', 6),
         'skipTicks' => $skip_ticks,
+        'phylogram_scale' => variable_get('tripal_phylogeny_default_phylogram_scale', 1),
       ],
       'org_colors' => $colors,
     ],
@@ -99,7 +101,8 @@ function tripal_phylogeny_prepare_tree_viewer($phylotree) {
  *
  * @ingroup tripal_phylogeny
  */
-function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
+function tripal_phylogeny_ajax_get_tree_json($phylotree_id)
+{
 
   $phylotree = chado_generate_var('phylotree', ['phylotree_id' => $phylotree_id]);
 
@@ -135,8 +138,7 @@ function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
         LEFT OUTER JOIN [chado_organism] co       ON co.organism_id = o.organism_id
       WHERE n.phylotree_id = :phylotree_id
     ";
-  }
-  else {
+  } else {
     $sql = "
       SELECT
         n.phylonode_id, n.parent_phylonode_id, n.label AS name, n.distance AS length,
@@ -165,13 +167,13 @@ function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
 
   if ($results) {
     while ($r = $results->fetchObject()) {
-      $phylonode_id = (int) $r->phylonode_id;
+      $phylonode_id = (int)$r->phylonode_id;
 
       // expect all nodes to have these properties
       $node = [
         'phylonode_id' => $phylonode_id,
-        'parent_phylonode_id' => (int) $r->parent_phylonode_id,
-        'length' => (double) $r->length,
+        'parent_phylonode_id' => (int)$r->parent_phylonode_id,
+        'length' => (double)$r->length,
         'cvterm_name' => $r->cvterm_name,
       ];
 
@@ -186,30 +188,28 @@ function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
       }
       // If this node is associated with a feature then add in the details
       if ($r->feature_id) {
-        $node['feature_id'] = (int) $r->feature_id;
+        $node['feature_id'] = (int)$r->feature_id;
         $node['feature_name'] = $r->feature_name;
         if (module_exists('tripal_phylogeny')) {
-          $node['feature_nid'] = (int) $r->feature_nid;
-        }
-        else {
+          $node['feature_nid'] = (int)$r->feature_nid;
+        } else {
           $entity_id = chado_get_record_entity_by_table('feature', $r->feature_id);
-          $node['feature_eid'] = (int) $entity_id;
+          $node['feature_eid'] = (int)$entity_id;
         }
       }
       // Add in the organism fields when they are available via the
       // phylonode_organism table.
       if ($r->organism_id) {
-        $node['organism_id'] = (int) $r->organism_id;
+        $node['organism_id'] = (int)$r->organism_id;
         $node['common_name'] = $r->common_name;
         $node['abbreviation'] = $r->abbreviation;
         $node['genus'] = $r->genus;
         $node['species'] = $r->species;
         if (module_exists('tripal_phylogeny')) {
-          $node['organism_nid'] = (int) $r->organism_nid;
-        }
-        else {
+          $node['organism_nid'] = (int)$r->organism_nid;
+        } else {
           $entity_id = chado_get_record_entity_by_table('organism', $r->organism_id);
-          $node['organism_eid'] = (int) $entity_id;
+          $node['organism_eid'] = (int)$entity_id;
         }
         // If the node does not have a name but is linked to an organism
         // then set the name to be that of the genus and species.
@@ -220,17 +220,16 @@ function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
       // Add in the organism fields when they are available via the
       // the phylonode.feature_id FK relationship.
       if ($r->fo_organism_id) {
-        $node['fo_organism_id'] = (int) $r->fo_organism_id;
+        $node['fo_organism_id'] = (int)$r->fo_organism_id;
         $node['fo_common_name'] = $r->fo_common_name;
         $node['fo_abbreviation'] = $r->fo_abbreviation;
         $node['fo_genus'] = $r->fo_genus;
         $node['fo_species'] = $r->fo_species;
         if (module_exists('tripal_phylogeny')) {
-          $node['fo_organism_nid'] = (int) $r->fo_organism_nid;
-        }
-        else {
+          $node['fo_organism_nid'] = (int)$r->fo_organism_nid;
+        } else {
           $entity_id = chado_get_record_entity_by_table('organism', $r->fo_organism_id);
-          $node['fo_organism_eid'] = (int) $entity_id;
+          $node['fo_organism_eid'] = (int)$entity_id;
         }
       }
 
@@ -244,8 +243,7 @@ function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
         $parent_ref = &$phylonodes[$node['parent_phylonode_id']];
         // Append node refernce to children.
         $parent_ref['children'][] = &$node;
-      }
-      else {
+      } else {
         $root_phylonode_ref = &$node;
       }
     }
@@ -262,7 +260,8 @@ function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
  *
  */
 
-function tripal_phylogeny_admin_phylotrees_listing() {
+function tripal_phylogeny_admin_phylotrees_listing()
+{
   $output = '';
 
   // set the breadcrumb
@@ -278,8 +277,7 @@ function tripal_phylogeny_admin_phylotrees_listing() {
   $view = views_embed_view('tripal_phylogeny_admin_phylotree', 'default');
   if (isset($view)) {
     $output .= $view;
-  }
-  else {
+  } else {
     $output .= '<p>The Phylotree module uses primarily views to provide an '
       . 'administrative interface. Currently one or more views needed for this '
       . 'administrative interface are disabled. <strong>Click each of the following links to '
@@ -297,7 +295,8 @@ function tripal_phylogeny_admin_phylotrees_listing() {
  * @param unknown $form
  * @param unknown $form_state
  */
-function tripal_phylogeny_default_plots_form($form, &$form_state) {
+function tripal_phylogeny_default_plots_form($form, &$form_state)
+{
   $form = [];
 
   $form['plot_settings'] = [
@@ -319,6 +318,19 @@ function tripal_phylogeny_default_plots_form($form, &$form_state) {
     '#size' => 5,
   ];
 
+  $form['plot_settings']['phylogram_scale'] = [
+    '#type' => 'select',
+    '#title' => t('Phylogram Scale'),
+    '#description' => 'Please specify the scale to use.',
+    '#default_value' => variable_get('tripal_phylogeny_default_phylogram_scale', 1),
+    '#options' => array(
+      1 => t('Linear'),
+      2 => t('Logarithmic'),
+    ),
+    '#size' => 2,
+  ];
+
+
   $form['node_settings'] = [
     '#type' => 'fieldset',
     '#title' => t('Node Settings'),
@@ -447,7 +459,8 @@ function tripal_phylogeny_default_plots_form($form, &$form_state) {
  *
  * @ingroup tripal_phylogeny
  */
-function tripal_phylogeny_default_plots_form_validate($form, &$form_state) {
+function tripal_phylogeny_default_plots_form_validate($form, &$form_state)
+{
 
 }
 
@@ -456,7 +469,8 @@ function tripal_phylogeny_default_plots_form_validate($form, &$form_state) {
  * @param unknown $form
  * @param unknown $form_state
  */
-function tripal_phylogeny_default_plots_form_submit($form, &$form_state) {
+function tripal_phylogeny_default_plots_form_submit($form, &$form_state)
+{
   // Rebuild this form after submission so that any changes are reflected in
   // the flat tables.
   $form_state['rebuild'] = TRUE;
@@ -467,6 +481,7 @@ function tripal_phylogeny_default_plots_form_submit($form, &$form_state) {
     variable_set('tripal_phylogeny_default_root_node_size', $form_state['values']['root_node_size']);
     variable_set('tripal_phylogeny_default_interior_node_size', $form_state['values']['interior_node_size']);
     variable_set('tripal_phylogeny_default_leaf_node_size', $form_state['values']['leaf_node_size']);
+    variable_set('tripal_phylogeny_default_phylogram_scale', $form_state['values']['phylogram_scale']);
 
     $num_orgs = $form_state['values']['num_orgs'];
     variable_set("tripal_phylogeny_num_orgs", $num_orgs);
@@ -491,7 +506,8 @@ function tripal_phylogeny_default_plots_form_submit($form, &$form_state) {
  *
  * @param unknown $variables
  */
-function theme_tripal_phylogeny_admin_org_color_tables($variables) {
+function theme_tripal_phylogeny_admin_org_color_tables($variables)
+{
   $fields = $variables['element'];
   $num_orgs = $fields['num_orgs']['#value'];
   $headers = ['Organism', 'Color', ''];
@@ -524,7 +540,8 @@ function theme_tripal_phylogeny_admin_org_color_tables($variables) {
  * @param $form
  * @param $form_state
  */
-function tripal_phylogeny_default_plots_form_ajax_callback($form, $form_state) {
+function tripal_phylogeny_default_plots_form_ajax_callback($form, $form_state)
+{
 
   return $form['node_settings']['org_table'];
-}
+}

+ 236 - 178
tripal_chado/theme/js/d3.phylogram.js

@@ -41,7 +41,7 @@
       selector: selector of an element that will contain the SVG
       nodes: JS object of nodes
     Options:
-      width       
+      width
         Width of the vis, will attempt to set a default based on the width of
         the container.
       height
@@ -63,219 +63,256 @@
         Skip the tick rule.
       skipBranchLengthScaling
         Make a dendrogram instead of a phylogram.
-  
+
   d3.phylogram.buildRadial(selector, nodes, options)
     Creates a radial dendrogram.
-    Options: same as build, but without diagonal, skipTicks, and 
+    Options: same as build, but without diagonal, skipTicks, and
       skipBranchLengthScaling
-  
+
   d3.phylogram.rightAngleDiagonal()
     Similar to d3.diagonal except it create an orthogonal crook instead of a
     smooth Bezier curve.
-    
+
   d3.phylogram.radialRightAngleDiagonal()
     d3.phylogram.rightAngleDiagonal for radial layouts.
 */
 
-if (!d3) { throw "d3 wasn't included!"};
-(function() {
+if (!d3) {
+  throw "d3 wasn't included!"
+}
+;
+(function () {
   d3.phylogram = {}
-  d3.phylogram.rightAngleDiagonal = function() {
-    var projection = function(d) { return [d.y, d.x]; }
-    
-    var path = function(pathData) {
-      return "M" + pathData[0] + ' ' + pathData[1] + " " + pathData[2];
+  d3.phylogram.rightAngleDiagonal = function () {
+    var projection = function (d) {
+      return [d.y, d.x];
+    }
+
+    var path = function (pathData) {
+      return "M" + pathData[0] + " " + pathData[1] + " " + pathData[2];
     }
-    
+
     function diagonal(diagonalPath, i) {
       var source = diagonalPath.source,
-          target = diagonalPath.target,
-          midpointX = (source.x + target.x) / 2,
-          midpointY = (source.y + target.y) / 2,
-          pathData = [source, {x: target.x, y: source.y}, target];
+        target = diagonalPath.target,
+        midpointX = (source.x + target.x) / 2,
+        midpointY = (source.y + target.y) / 2,
+        pathData = [source, {x: target.x, y: source.y}, target];
       pathData = pathData.map(projection);
-      return path(pathData)
+      return path(pathData);
     }
-    
-    diagonal.projection = function(x) {
-      if (!arguments.length) return projection;
+
+    diagonal.projection = function (x) {
+      if (!arguments.length) {
+        return projection;
+      }
       projection = x;
       return diagonal;
     };
-    
-    diagonal.path = function(x) {
-      if (!arguments.length) return path;
+
+    diagonal.path = function (x) {
+      if (!arguments.length) {
+        return path;
+      }
       path = x;
       return diagonal;
     };
-    
+
     return diagonal;
   }
-  
-  d3.phylogram.radialRightAngleDiagonal = function() {
+
+  d3.phylogram.radialRightAngleDiagonal = function () {
     return d3.phylogram.rightAngleDiagonal()
-      .path(function(pathData) {
+      .path(function (pathData) {
         var src = pathData[0],
-            mid = pathData[1],
-            dst = pathData[2],
-            radius = Math.sqrt(src[0]*src[0] + src[1]*src[1]),
-            srcAngle = d3.phylogram.coordinateToAngle(src, radius),
-            midAngle = d3.phylogram.coordinateToAngle(mid, radius),
-            clockwise = Math.abs(midAngle - srcAngle) > Math.PI ? midAngle <= srcAngle : midAngle > srcAngle,
-            rotation = 0,
-            largeArc = 0,
-            sweep = clockwise ? 0 : 1;
+          mid = pathData[1],
+          dst = pathData[2],
+          radius = Math.sqrt(src[0] * src[0] + src[1] * src[1]),
+          srcAngle = d3.phylogram.coordinateToAngle(src, radius),
+          midAngle = d3.phylogram.coordinateToAngle(mid, radius),
+          clockwise = Math.abs(midAngle - srcAngle) > Math.PI ? midAngle <= srcAngle : midAngle > srcAngle,
+          rotation = 0,
+          largeArc = 0,
+          sweep = clockwise ? 0 : 1;
         return 'M' + src + ' ' +
-          "A" + [radius,radius] + ' ' + rotation + ' ' + largeArc+','+sweep + ' ' + mid +
+          "A" + [radius, radius] + ' ' + rotation + ' ' + largeArc + ',' + sweep + ' ' + mid +
           'L' + dst;
       })
-      .projection(function(d) {
+      .projection(function (d) {
         var r = d.y, a = (d.x - 90) / 180 * Math.PI;
         return [r * Math.cos(a), r * Math.sin(a)];
-      })
+      });
   }
-  
+
   // Convert XY and radius to angle of a circle centered at 0,0
-  d3.phylogram.coordinateToAngle = function(coord, radius) {
+  d3.phylogram.coordinateToAngle = function (coord, radius) {
     var wholeAngle = 2 * Math.PI,
-        quarterAngle = wholeAngle / 4
-    
+      quarterAngle = wholeAngle / 4
+
     var coordQuad = coord[0] >= 0 ? (coord[1] >= 0 ? 1 : 2) : (coord[1] >= 0 ? 4 : 3),
-        coordBaseAngle = Math.abs(Math.asin(coord[1] / radius))
-    
+      coordBaseAngle = Math.abs(Math.asin(coord[1] / radius))
+
     // Since this is just based on the angle of the right triangle formed
-    // by the coordinate and the origin, each quad will have different 
+    // by the coordinate and the origin, each quad will have different
     // offsets
     switch (coordQuad) {
       case 1:
         coordAngle = quarterAngle - coordBaseAngle
-        break
+        break;
       case 2:
         coordAngle = quarterAngle + coordBaseAngle
-        break
+        break;
       case 3:
-        coordAngle = 2*quarterAngle + quarterAngle - coordBaseAngle
-        break
+        coordAngle = 2 * quarterAngle + quarterAngle - coordBaseAngle
+        break;
       case 4:
-        coordAngle = 3*quarterAngle + coordBaseAngle
+        coordAngle = 3 * quarterAngle + coordBaseAngle
     }
-    return coordAngle
+    return coordAngle;
   }
 
-  function scaleBranchLengths(nodes, w) {
+  function scaleBranchLengths(nodes, w, options) {
     // Visit all nodes and adjust y pos width distance metric
-    var visitPreOrder = function(root, callback) {
+    var visitPreOrder = function (root, callback) {
       callback(root)
       if (root.children) {
-        for (var i = root.children.length - 1; i >= 0; i--){
+        for (var i = root.children.length - 1; i >= 0; i--) {
           visitPreOrder(root.children[i], callback);
-        };
+        }
       }
     }
-    visitPreOrder(nodes[0], function(node) {
-      node.rootDist = (node.parent ? node.parent.rootDist : 0) + (node.length || 0)
+    visitPreOrder(nodes[0], function (node) {
+      node.rootDist = (node.parent ? node.parent.rootDist : 0) + (node.length || 0);
     })
-    var rootDists = nodes.map(function(n) { return n.rootDist; });
-    var yscale = d3.scale.linear()
-      .domain([0, d3.max(rootDists)])
-      .range([0, w]);
-    visitPreOrder(nodes[0], function(node) {
-      node.y = yscale(node.rootDist)
+    var rootDists = nodes.map(function (n) {
+      return n.rootDist;
+    });
+    var yscale;
+    switch (parseInt(options.phylogram_scale)) {
+      case 1:
+        yscale = d3.scale.linear()
+          .domain([0, d3.max(rootDists)])
+          .range([0, w]);
+        break;
+      case 2:
+        yscale = d3.scale.log()
+          .domain([0.01, d3.max(rootDists)])
+          .range([0, w]);
+        break;
+      default: // shouldn't happen
+        break;
+    }
+    visitPreOrder(nodes[0], function (node) {
+      node.y = yscale(node.rootDist);
     })
-    return yscale
+    return yscale;
   }
-  
-  d3.phylogram.build = function(selector, nodes, options) {
+
+  d3.phylogram.build = function (selector, nodes, options) {
     options = options || {}
     var w = options.width || d3.select(selector).style('width') || d3.select(selector).attr('width'),
-        h = options.height || d3.select(selector).style('height') || d3.select(selector).attr('height'),
-        w = parseInt(w),
-        h = parseInt(h);
-    var fill = options.fill || function(d) {
+      h = options.height || d3.select(selector).style('height') || d3.select(selector).attr('height'),
+      w = parseInt(w),
+      h = parseInt(h);
+    var fill = options.fill || function (d) {
       return 'cyan';
     };
-    var size = options.size || function(d) {
+    var size = options.size || function (d) {
       return 6;
     }
-    var nodeMouseOver = options.nodeMouseOver || function(d) {};
-    var nodeMouseOut  = options.nodeMouseOut  || function(d) {};
-    var nodeMouseDown = options.nodeMouseDown || function(d) {};
-    
+    var nodeMouseOver = options.nodeMouseOver || function (d) {
+    };
+    var nodeMouseOut = options.nodeMouseOut || function (d) {
+    };
+    var nodeMouseDown = options.nodeMouseDown || function (d) {
+    };
+
     var tree = options.tree || d3.layout.cluster()
       .size([h, w])
-      .sort(function(node) { return node.children ? node.children.length : -1; })
-      .children(options.children || function(node) {
+      .sort(function (node) {
+        return node.children ? node.children.length : -1;
+      })
+      .children(options.children || function (node) {
         return node.children;
       });
     var diagonal = options.diagonal || d3.phylogram.rightAngleDiagonal();
     var vis = options.vis || d3.select(selector).append("svg:svg")
-        .attr("width", w + 300)
-        .attr("height", h + 30)
-        .append("svg:g")
-        .attr("transform", "translate(20, 20)");
-    var nodes = tree(nodes);
-    
+      .attr("width", w + 300)
+      .attr("height", h + 30)
+      .append("svg:g")
+      .attr("transform", "translate(20, 20)");
+    nodes = tree(nodes);
+
     if (options.skipBranchLengthScaling) {
-      var yscale = d3.scale.linear()
-        .domain([0, w])
-        .range([0, w]);
-    } 
-    else {
-      var yscale = scaleBranchLengths(nodes, w)
+      switch (options.phylogram_scale) {
+        case 1:
+          var yscale = d3.scale.linear()
+            .domain([0, d3.max(rootDists)])
+            .range([0, w]);
+        case 2:
+          var yscale = d3.scale.log()
+            .domain([0.01, d3.max(rootDists)])
+            .range([0, w]);
+      }
+
+    } else {
+      yscale = scaleBranchLengths(nodes, w, options);
     }
-    
+
     if (!options.skipTicks) {
       vis.selectAll('line')
-          .data(yscale.ticks(10))
-          .enter().append('svg:line')
-          .attr('y1', 0)
-          .attr('y2', h)
-          .attr('x1', yscale)
-          .attr('x2', yscale)
-          .attr("stroke", "#ddd");
+        .data(yscale.ticks(10))
+        .enter().append('svg:line')
+        .attr('y1', 0)
+        .attr('y2', h)
+        .attr('x1', yscale)
+        .attr('x2', yscale)
+        .attr("stroke", "#ddd");
 
       vis.selectAll("text.rule")
-          .data(yscale.ticks(10))
-          .enter().append("svg:text")
-          .attr("class", "rule")
-          .attr("x", yscale)
-          .attr("y", 0)
-          .attr("dy", -3)
-          .attr("text-anchor", "middle")
-          .attr('font-size', '9px')
-          .attr('fill', 'grey')
-          .text(function(d) { return Math.round(d*100) / 100; });
+        .data(yscale.ticks(10))
+        .enter().append("svg:text")
+        .attr("class", "rule")
+        .attr("x", yscale)
+        .attr("y", 0)
+        .attr("dy", -3)
+        .attr("text-anchor", "middle")
+        .attr('font-size', '9px')
+        .attr('fill', 'grey')
+        .text(function (d) {
+          return Math.round(d * 100) / 100;
+        });
     }
-        
+
     var link = vis.selectAll("path.link")
-        .data(tree.links(nodes))
-        .enter().append("svg:path")
-        .attr("class", "link")
-        .attr("d", diagonal)
-        .attr("fill", "none")
-        .attr("stroke", "#aaa")
-        .attr("stroke-width", "4px");
-        
+      .data(tree.links(nodes))
+      .enter().append("svg:path")
+      .attr("class", "link")
+      .attr("d", diagonal)
+      .attr("fill", "none")
+      .attr("stroke", "#aaa")
+      .attr("stroke-width", "4px");
+
     var node = vis.selectAll("g.node")
-        .data(nodes)
-        .enter().append("svg:g")
-        .attr("class", function(n) {
-          if (n.children) {
-            if (n.depth == 0) {
-              return "root node"
-            } 
-            else {
-              return "inner node"
-            }
-          } 
-          else {
-            return "leaf node"
+      .data(nodes)
+      .enter().append("svg:g")
+      .attr("class", function (n) {
+        if (n.children) {
+          if (n.depth == 0) {
+            return "root node"
+          } else {
+            return "inner node"
           }
-        })
-        .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
+        } else {
+          return "leaf node"
+        }
+      })
+      .attr("transform", function (d) {
+        return "translate(" + d.y + "," + d.x + ")";
+      })
 
-     // style the root node
-     vis.selectAll('g.root.node')
+    // style the root node
+    vis.selectAll('g.root.node')
       .append('svg:circle')
       .on('click', nodeMouseDown)
       .on('mouseover', nodeMouseOver)
@@ -305,16 +342,16 @@ if (!d3) { throw "d3 wasn't included!"};
       .attr('stroke', 'dimgrey')
       .attr('stroke-width', '2px')
       .attr('fill', 'white');
-    
+
     if (!options.skipLabels) {
       vis.selectAll('g.inner.node')
         .append("svg:text")
-          .attr("dx", -6)
-          .attr("dy", -6)
-          .attr("text-anchor", 'end')
-          .attr('font-size', '9px')
-          .attr('fill', 'black')
-        //.text(function(d) { return d.length.toFixed(4); }); // hide length
+        .attr("dx", -6)
+        .attr("dy", -6)
+        .attr("text-anchor", 'end')
+        .attr('font-size', '9px')
+        .attr('fill', 'black')
+      //.text(function(d) { return d.length.toFixed(4); }); // hide length
 
       vis.selectAll('g.leaf.node').append("svg:text")
         .attr("dx", 8)
@@ -323,80 +360,101 @@ if (!d3) { throw "d3 wasn't included!"};
         .attr('font-family', 'Helvetica Neue, Helvetica, sans-serif')
         .attr('font-size', '10px')
         .attr('fill', 'black')
-        .text(function(d) {
+        .text(function (d) {
           // return d.name + ' (' + d.length.toFixed(4) + ')'; // hide length
           return d.name;
-         });
+        });
     }
     return {tree: tree, vis: vis}
   }
-  
-  d3.phylogram.buildRadial = function(selector, nodes, options) {
+
+  d3.phylogram.buildRadial = function (selector, nodes, options) {
     options = options || {};
-    
-    var fill = options.fill || function(d) {
+
+    var fill = options.fill || function (d) {
       return 'cyan';
     };
-    var size = options.size || function(d) {
+    var size = options.size || function (d) {
       return 6;
     }
-    var nodeMouseOver = options.nodeMouseOver || function(d) {};
-    var nodeMouseOut = options.nodeMouseOut || function(d) {};
-    var nodeMouseDown = options.nodeMouseDown || function(d) {};
-    
+    var nodeMouseOver = options.nodeMouseOver || function (d) {
+    };
+    var nodeMouseOut = options.nodeMouseOut || function (d) {
+    };
+    var nodeMouseDown = options.nodeMouseDown || function (d) {
+    };
+
     var w = options.width || d3.select(selector).style('width') || d3.select(selector).attr('width'),
-        r = w / 2,
-        labelWidth = options.skipLabels ? 10 : options.labelWidth || 120;
-    
+      r = w / 2,
+      labelWidth = options.skipLabels ? 10 : options.labelWidth || 120;
+
     var vis = d3.select(selector).append("svg:svg")
-        .attr("width", r * 2)
-        .attr("height", r * 2)
-        .append("svg:g")
-        .attr("transform", "translate(" + r + "," + r + ")");
-        
+      .attr("width", r * 2)
+      .attr("height", r * 2)
+      .append("svg:g")
+      .attr("transform", "translate(" + r + "," + r + ")");
+
     var tree = d3.layout.tree()
       .size([360, r - labelWidth])
-      .sort(function(node) { return node.children ? node.children.length : -1; })
-      .children(options.children || function(node) {
+      .sort(function (node) {
+        return node.children ? node.children.length : -1;
+      })
+      .children(options.children || function (node) {
         return node.children;
       })
-      .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
+      .separation(function (a, b) {
+        return (a.parent == b.parent ? 1 : 2) / a.depth;
+      });
 
     var phylogram = d3.phylogram.build(selector, nodes, {
       vis: vis,
       tree: tree,
-      fill : fill,
+      fill: fill,
       size: size,
-      nodeMouseOver : nodeMouseOver,
-      nodeMouseOut : nodeMouseOut,
-      nodeMouseDown : nodeMouseDown,
+      nodeMouseOver: nodeMouseOver,
+      nodeMouseOut: nodeMouseOut,
+      nodeMouseDown: nodeMouseDown,
       skipBranchLengthScaling: true,
       skipTicks: true,
       skipLabels: options.skipLabels,
       diagonal: d3.phylogram.radialRightAngleDiagonal()
     })
     vis.selectAll('g.node')
-      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
-    
+      .attr("transform", function (d) {
+        return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")";
+      })
+
     if (!options.skipLabels) {
       vis.selectAll('g.leaf.node text')
-        .attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
+        .attr("dx", function (d) {
+          return d.x < 180 ? 8 : -8;
+        })
         .attr("dy", ".31em")
-        .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
-        .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
+        .attr("text-anchor", function (d) {
+          return d.x < 180 ? "start" : "end";
+        })
+        .attr("transform", function (d) {
+          return d.x < 180 ? null : "rotate(180)";
+        })
         .attr('font-family', 'Helvetica Neue, Helvetica, sans-serif')
         .attr('font-size', '10px')
         .attr('fill', 'black')
-        .text(function(d) {
+        .text(function (d) {
           return d.name;
         });
 
       vis.selectAll('g.inner.node text')
-        .attr("dx", function(d) { return d.x < 180 ? -6 : 6; })
-        .attr("text-anchor", function(d) { return d.x < 180 ? "end" : "start"; })
-        .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; });
+        .attr("dx", function (d) {
+          return d.x < 180 ? -6 : 6;
+        })
+        .attr("text-anchor", function (d) {
+          return d.x < 180 ? "end" : "start";
+        })
+        .attr("transform", function (d) {
+          return d.x < 180 ? null : "rotate(180)";
+        });
     }
-    
+
     return {tree: tree, vis: vis}
   }
 }());

+ 23 - 16
tripal_chado/theme/js/tripal_phylogeny.js

@@ -1,16 +1,16 @@
 /* phylotree d3js graphs */
 
 (function ($) {
-    
+
   "use strict";
 
   // Will be dynamically sized.
-  var height = 0; 
+  var height = 0;
 
   // Store our function as a property of Drupal.behaviors.
   Drupal.behaviors.TripalPhylotree = {
     attach: function (context, settings) {
-      
+
       // Retrieve the data for this tree.
       var data_url = Drupal.settings.tripal_chado.phylotree_url;
       $.getJSON(data_url, function(treeData) {
@@ -25,13 +25,13 @@
     var size;
     var tree_options = Drupal.settings.tripal_chado.tree_options;
     if (d.cvterm_name == "phylo_root") {
-      size = tree_options['root_node_size']; 
+      size = tree_options['root_node_size'];
     }
     if (d.cvterm_name == "phylo_interior") {
-      size = tree_options['interior_node_size']; 
+      size = tree_options['interior_node_size'];
     }
     if (d.cvterm_name == "phylo_leaf") {
-      size = tree_options['leaf_node_size']; 
+      size = tree_options['leaf_node_size'];
     }
     return size;
   }
@@ -40,14 +40,15 @@
   var phylogeny_organism_color = function(d) {
     var organism_color = Drupal.settings.tripal_chado.org_colors;
     var color = null;
-    if (d.genus) {
-      color = organism_color[d.organism_id];
+
+    if (d.fo_genus) {
+      color = organism_color[d.fo_organism_id];
     }
-    if (color) { 
-      return color; 
+    if (color) {
+      return color;
     }
-    else { 
-      return 'grey'; 
+    else {
+      return 'grey';
     }
   };
 
@@ -64,7 +65,7 @@
       txt.attr('font-weight', 'bold');
     }
   };
-  
+
   // Callback for mouseout event on graph node d.
   var phylogeny_node_mouse_out = function(d) {
     var el = $(this);
@@ -81,7 +82,7 @@
       circle.attr('fill', 'white');
     }
   };
-  
+
   // Callback for mousedown/click event on graph node d.
   var phylogeny_node_mouse_down = function(d) {
     var el = $(this);
@@ -96,7 +97,12 @@
       }
     }
     else {
-      // If this node is not associated with a feature but it has an 
+      if(d.feature_eid) {
+        window.location.href = baseurl + '/bio_data/' + d.feature_eid;
+
+        return;
+      }
+      // If this node is not associated with a feature but it has an
       // organism node then this is a taxonomic node and we want to
       // link it to the organism page.
       if (!d.feature_id && d.organism_nid) {
@@ -121,7 +127,8 @@
       'nodeMouseOver' : phylogeny_node_mouse_over,
       'nodeMouseOut' : phylogeny_node_mouse_out,
       'nodeMouseDown' : phylogeny_node_mouse_down,
-      'skipTicks' : tree_options['skipTicks']
+      'skipTicks' : tree_options['skipTicks'],
+      'phylogram_scale' : tree_options['phylogram_scale']
     });
   }