tripal_phylogeny.module

  1. 2.x tripal_phylogeny/tripal_phylogeny.module
  2. 3.x legacy/tripal_phylogeny/tripal_phylogeny.module

Integrates the Chado Phylotree module with Drupal Nodes & Views

File

tripal_phylogeny/tripal_phylogeny.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Integrates the Chado Phylotree module with Drupal Nodes & Views
  5. */
  6. /**
  7. * @defgroup tripal_phylogeny Phylotree Module
  8. * @ingroup tripal_modules
  9. * @{
  10. * Integrates the Chado Phylotree module with Drupal Nodes
  11. * @}
  12. */
  13. require_once 'api/tripal_phylogeny.api.inc';
  14. require_once 'theme/tripal_phylogeny.theme.inc';
  15. require_once 'includes/tripal_phylogeny.admin.inc';
  16. require_once 'includes/tripal_phylogeny.chado_node.inc';
  17. require_once 'includes/tripal_phylogeny.import_tree.inc';
  18. require_once 'includes/tripal_phylogeny.taxonomy.inc';
  19. /**
  20. * Implements hook_permission().
  21. *
  22. * Set the permission types that the chado module uses. Essentially we
  23. * want permissionis that protect creation, editing and deleting of chado
  24. * data objects
  25. *
  26. * @ingroup tripal_phylogeny
  27. */
  28. function tripal_phylogeny_permission() {
  29. return array(
  30. 'access chado_phylotree content' => array(
  31. 'title' => t('View Phylotrees'),
  32. 'description' => t('Allow users to view phylotree pages.'),
  33. ),
  34. 'administer tripal phylotree' => array(
  35. 'title' => t('Administer Phylotrees'),
  36. 'description' => t('Allow users to administer all phylotrees.'),
  37. ),
  38. );
  39. }
  40. /**
  41. * Implements hook_menu().
  42. *
  43. * Menu items are automatically added for the new node types created
  44. * by this module to the 'Create Content' Navigation menu item. This function
  45. * adds more menu items needed for this module.
  46. *
  47. * @ingroup tripal_phylogeny
  48. */
  49. function tripal_phylogeny_menu() {
  50. $items = array();
  51. // administration landing page. currently has no content but is
  52. // apparently required for the Sync and Help links to work.
  53. $items['admin/tripal/chado/tripal_phylogeny'] = array(
  54. 'title' => 'Phylogeny and Taxonomy',
  55. 'description' => 'Phylogenetic and taxonomic trees.',
  56. 'page callback' => 'tripal_phylogeny_admin_phylotrees_listing',
  57. 'access arguments' => array('administer tripal phylotree'),
  58. 'type' => MENU_NORMAL_ITEM,
  59. );
  60. // help menu
  61. $items['admin/tripal/chado/tripal_phylogeny/help'] = array(
  62. 'title' => 'Help',
  63. 'description' => 'Basic Description of Tripal Phylotree Module Functionality',
  64. 'page callback' => 'theme',
  65. 'page arguments' => array('tripal_phylogeny_help'),
  66. 'access arguments' => array('administer tripal phylotree'),
  67. 'type' => MENU_LOCAL_TASK,
  68. 'weight' => 10
  69. );
  70. // configuration menu item
  71. $items['admin/tripal/chado/tripal_phylogeny/configuration'] = array(
  72. 'title' => 'Settings',
  73. 'description' => 'Configure the Tripal Phylotree module',
  74. 'page callback' => 'drupal_get_form',
  75. 'page arguments' => array('tripal_phylogeny_admin'),
  76. 'access arguments' => array('administer tripal phylotree'),
  77. 'type' => MENU_LOCAL_TASK,
  78. 'weight' => 1
  79. );
  80. $items['admin/tripal/chado/tripal_phylogeny/plots'] = array(
  81. 'title' => 'Plot Defaults',
  82. 'description' => 'Set defaults for the trees',
  83. 'page callback' => 'drupal_get_form',
  84. 'page arguments' => array('tripal_phylogeny_default_plots_form'),
  85. 'access arguments' => array('administer tripal phylotree'),
  86. 'type' => MENU_LOCAL_TASK,
  87. 'weight' => 2
  88. );
  89. // sync menu item (will be rendered as a tab by tripal)
  90. $items['admin/tripal/chado/tripal_phylogeny/sync'] = array(
  91. 'title' => ' Sync',
  92. 'description' => 'Create pages on this site for phylotrees stored in Chado',
  93. 'page callback' => 'drupal_get_form',
  94. 'page arguments' => array('chado_node_sync_form', 'tripal_phylogeny', 'chado_phylotree'),
  95. 'access arguments' => array('administer tripal phylotree'),
  96. 'type' => MENU_LOCAL_TASK,
  97. 'weight' => 3
  98. );
  99. // Enable admin view
  100. $items['admin/tripal/chado/tripal_phylogeny/views/phylotree/enable'] = array(
  101. 'title' => 'Enable Phylotree Administrative View',
  102. 'page callback' => 'tripal_enable_view',
  103. 'page arguments' => array('tripal_phylogeny_admin_phylotree', 'admin/tripal/chado/tripal_phylogeny'),
  104. 'access arguments' => array('administer tripal phylotree'),
  105. 'type' => MENU_CALLBACK,
  106. );
  107. // Data Loaders
  108. $items['admin/tripal/loaders/newic_phylotree_loader'] = array(
  109. 'title' => 'Phylogenetic Trees (Newic format)',
  110. 'description' => 'Loads phylogenetic trees in Newic format. (Redirects to create a phylogenetic tree content type)',
  111. 'page callback' => 'drupal_goto',
  112. 'page arguments' => array('node/add/chado-phylotree'),
  113. 'access arguments' => array('administer tripal phylotree'),
  114. 'type' => MENU_NORMAL_ITEM,
  115. );
  116. $items['admin/tripal/loaders/ncbi_taxonomy_loader'] = array(
  117. 'title' => 'NCBI Taxonomy Loader',
  118. 'description' => 'Loads taxonomic details about installed organisms.',
  119. 'page callback' => 'drupal_get_form',
  120. 'page arguments' => array('tripal_phylogeny_taxonomy_load_form'),
  121. 'access arguments' => array('administer tripal phylotree'),
  122. 'file' => '/includes/tripal_phylogeny.taxonomy.inc',
  123. 'type' => MENU_NORMAL_ITEM,
  124. );
  125. $items['taxonomy_view'] = array(
  126. 'title' => 'Taxonomy',
  127. 'description' => 'Taxonomic view of the species available on this site.',
  128. 'page callback' => 'tripal_phylogeny_taxonomy_view',
  129. 'access arguments' => array('access taxonomy content'),
  130. 'file' => '/includes/tripal_phylogeny.taxonomy.inc',
  131. 'type' => MENU_NORMAL_ITEM,
  132. );
  133. // create a route for viewing json of all phylonodes having this phylotree_id
  134. $items['ajax/chado_phylotree/%/json'] = array(
  135. 'page callback' => 'tripal_phylogeny_ajax_get_tree_json',
  136. 'page arguments' => array(2),
  137. // allow all anonymous http clients
  138. 'access callback' => TRUE
  139. );
  140. return $items;
  141. }
  142. /**
  143. * Implements hook_search_biological_data_views().
  144. *
  145. * Adds the described views to the "Search Data" Page created by Tripal Views
  146. */
  147. function tripal_phylogeny_search_biological_data_views() {
  148. return array(
  149. 'tripal_phylogeny_user_phylotree' => array(
  150. 'machine_name' => 'tripal_phylogeny_user_phylotree',
  151. 'human_name' => 'Phylogenetic Trees',
  152. 'description' => 'Gene trees, species trees, etc.',
  153. 'link' => 'chado/phylotree'
  154. ),
  155. );
  156. }
  157. /**
  158. * Implements hook_views_api().
  159. *
  160. * Essentially this hook tells drupal that there is views support for
  161. * for this module which then includes tripal_db.views.inc where all the
  162. * views integration code is
  163. *
  164. * @ingroup tripal_phylogeny
  165. */
  166. function tripal_phylogeny_views_api() {
  167. return array(
  168. 'api' => 3.0,
  169. );
  170. }
  171. /**
  172. * Implements hook_theme().
  173. *
  174. * We need to let drupal know about our theme functions and their arguments.
  175. * We create theme functions to allow users of the module to customize the
  176. * look and feel of the output generated in this module
  177. *
  178. * @ingroup tripal_phylogeny
  179. */
  180. function tripal_phylogeny_theme($existing, $type, $theme, $path) {
  181. $core_path = drupal_get_path('module', 'tripal_core');
  182. $items = array(
  183. // built-in theme
  184. 'node__chado_phylotree' => array(
  185. 'template' => 'node--chado-generic',
  186. 'render element' => 'node',
  187. 'base hook' => 'node',
  188. 'path' => "$core_path/theme/templates",
  189. ),
  190. // base template for this page (default tab) includes the phylogram
  191. 'tripal_phylogeny_base' => array(
  192. 'variables' => array('node' => NULL),
  193. 'template' => 'tripal_phylogeny_base',
  194. 'path' => "$path/theme/templates",
  195. ),
  196. // Template for the phylogram.
  197. 'tripal_phylogeny_phylogram' => array(
  198. 'variables' => array('node' => NULL),
  199. 'template' => 'tripal_phylogeny_phylogram',
  200. 'path' => "$path/theme/templates",
  201. ),
  202. // Template for the taxonomic tree.
  203. 'tripal_phylogeny_taxonomic_tree' => array(
  204. 'variables' => array('node' => NULL),
  205. 'template' => 'tripal_phylogeny_taxonomic_tree',
  206. 'path' => "$path/theme/templates",
  207. ),
  208. // partial for organisms block
  209. 'tripal_phylogeny_organisms' => array(
  210. 'variables' => array('node' => NULL),
  211. 'template' => 'tripal_phylogeny_organisms',
  212. 'path' => "$path/theme/templates",
  213. ),
  214. // partial for cross references block
  215. 'tripal_phylogeny_references' => array(
  216. 'variables' => array('node' => NULL),
  217. 'template' => 'tripal_phylogeny_references',
  218. 'path' => "$path/theme/templates",
  219. ),
  220. // partial for cross references block
  221. 'tripal_phylogeny_analysis' => array(
  222. 'variables' => array('node' => NULL),
  223. 'template' => 'tripal_phylogeny_analysis',
  224. 'path' => "$path/theme/templates",
  225. ),
  226. // partial for teaser view
  227. 'tripal_phylogeny_teaser' => array(
  228. 'variables' => array('node' => NULL),
  229. 'template' => 'tripal_phylogeny_teaser',
  230. 'path' => "$path/theme/templates",
  231. ),
  232. // FORM THEMES
  233. // Theme function for the project table in admin projects form
  234. 'tripal_phylogeny_admin_org_color_tables' => array(
  235. 'render element' => 'element',
  236. )
  237. );
  238. return $items;
  239. }
  240. /**
  241. * Implements hook_help().
  242. * Adds a help page to the module list
  243. *
  244. * @ingroup tripal_phylogeny
  245. */
  246. function tripal_phylogeny_help ($path, $arg) {
  247. if ($path == 'admin/help#tripal_phylogeny') {
  248. return theme('tripal_phylogeny_help', array());
  249. }
  250. }
  251. /**
  252. * Get json representation of a phylotree id.
  253. *
  254. * This function is meant to be called via AJAX.
  255. *
  256. * @param int $phylotree_id
  257. * the ID of the phylotree node.
  258. *
  259. * @return string json
  260. *
  261. * @ingroup tripal_phylogeny
  262. */
  263. function tripal_phylogeny_ajax_get_tree_json($phylotree_id) {
  264. $phylotree = chado_generate_var('phylotree', array('phylotree_id' => $phylotree_id));
  265. // This SQL gets all of the phylonodes for a given tree as well as the
  266. // features and organisms with which it is assocaited. Each phylonode
  267. // can be associated with an orgnaism in one of two ways: 1) via a
  268. // feature linked by the phylonode.feature_id field or 2) via a
  269. // a record in the phylonde_organsim table. Therefore both types of
  270. // organism records are returned in the query below, but those
  271. // retrieved via a FK link on features are prefixed with 'fo_'.
  272. $sql = "
  273. SELECT
  274. n.phylonode_id, n.parent_phylonode_id, n.label AS name, n.distance AS length,
  275. f.feature_id, f.name AS feature_name,
  276. cvt.name AS cvterm_name,
  277. o.organism_id, o.common_name, o.abbreviation, o.genus, o.species,
  278. fo.organism_id AS fo_organism_id, fo.common_name AS fo_common_name,
  279. fo.abbreviation AS fo_abbreviation, fo.genus as fo_genus, fo.species AS fo_species,
  280. cf.nid AS feature_node_id,
  281. fco.nid AS fo_organism_node_id,
  282. co.nid AS organism_node_id
  283. FROM {phylonode} n
  284. LEFT OUTER JOIN {cvterm} cvt ON n.type_id = cvt.cvterm_id
  285. LEFT OUTER JOIN {feature} f ON n.feature_id = f.feature_id
  286. LEFT OUTER JOIN [chado_feature] cf ON cf.feature_id = f.feature_id
  287. LEFT OUTER JOIN {organism} fo ON f.organism_id = fo.organism_id
  288. LEFT OUTER JOIN [chado_organism] fco ON fco.organism_id = fo.organism_id
  289. LEFT OUTER JOIN {phylonode_organism} po ON po.phylonode_id = n.phylonode_id
  290. LEFT OUTER JOIN {organism} o ON PO.organism_id = o.organism_id
  291. LEFT OUTER JOIN [chado_organism] co ON co.organism_id = o.organism_id
  292. WHERE n.phylotree_id = :phylotree_id
  293. ";
  294. $args = array(':phylotree_id' => $phylotree_id);
  295. $result = chado_query($sql, $args);
  296. // Fetch all the phylonodes into an assoc array indexed by phylonode_id.
  297. // Convert from resultset record to array, fixing datatypes. chado_query
  298. // returns numeric as string and fun stuff like that.
  299. $phylonodes = array();
  300. $root_phylonode_ref = null;
  301. foreach ($result as $r) {
  302. $phylonode_id = (int) $r->phylonode_id;
  303. // expect all nodes to have these properties
  304. $node = array(
  305. 'phylonode_id' => $phylonode_id,
  306. 'parent_phylonode_id' => (int) $r->parent_phylonode_id,
  307. 'length' => (double) $r->length,
  308. 'cvterm_name' => $r->cvterm_name
  309. );
  310. // If the nodes are taxonomic then set an equal distance
  311. if ($phylotree->type_id->name == 'taxonomy') {
  312. $node['length'] = 0.001;
  313. }
  314. // Other props may exist only for leaf nodes
  315. if ($r->name) {
  316. $node['name'] = $r->name;
  317. }
  318. // If this node is associated with a feature then add in the details
  319. if ($r->feature_id) {
  320. $node['feature_id'] = (int) $r->feature_id;
  321. $node['feature_name'] = $r->feature_name;
  322. $node['feature_node_id'] = (int) $r->feature_node_id;
  323. }
  324. // Add in the organism fields when they are available via the
  325. // phylonode_organism table.
  326. if ($r->organism_id) {
  327. $node['organism_id'] = (int) $r->organism_id;
  328. $node['common_name'] = $r->common_name;
  329. $node['abbreviation'] = $r->abbreviation;
  330. $node['genus'] = $r->genus;
  331. $node['species'] = $r->species;
  332. $node['organism_node_id'] = (int) $r->organism_node_id;
  333. // If the node does not have a name but is linked to an organism
  334. // then set the name to be that of the genus and species.
  335. if (!$r->name) {
  336. $node['name'] = $r->genus . ' ' . $r->species;
  337. }
  338. }
  339. // Add in the organism fields when they are available via the
  340. // the phylonode.feature_id FK relationship.
  341. if ($r->fo_organism_id) {
  342. $node['fo_organism_id'] = (int) $r->fo_organism_id;
  343. $node['fo_common_name'] = $r->fo_common_name;
  344. $node['fo_abbreviation'] = $r->fo_abbreviation;
  345. $node['fo_genus'] = $r->fo_genus;
  346. $node['fo_species'] = $r->fo_species;
  347. $node['fo_organism_node_id'] = (int) $r->fo_organism_node_id;
  348. }
  349. // Add this node to the list, organized by ID.
  350. $phylonodes[$phylonode_id] = $node;
  351. }
  352. // Populate the children[] arrays for each node.
  353. foreach ($phylonodes as $key => &$node) {
  354. if ($node['parent_phylonode_id'] !== 0) {
  355. $parent_ref = &$phylonodes[ $node['parent_phylonode_id']];
  356. // Append node refernce to children.
  357. $parent_ref['children'][] = &$node;
  358. }
  359. else {
  360. $root_phylonode_ref = &$node;
  361. }
  362. }
  363. // dump datastructure as json to browser. drupal sets the mime-type correctly.
  364. drupal_json_output($root_phylonode_ref);
  365. }