trees.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. <?php
  2. /**
  3. * @file
  4. * @todo Stephen describe this file
  5. */
  6. /**
  7. * Renders the cv_list form
  8. *
  9. * @ingroup tripal_cv
  10. */
  11. function tripal_cv_show_browser() {
  12. $content = drupal_get_form('tripal_cv_list_form');
  13. $content .= "
  14. <div id=\"cv_browser\"></div>
  15. ";
  16. return $content;
  17. }
  18. /**
  19. * Generates JSON used for generating an exapandable tree of terms from
  20. * a controlled vocabulary that has associated counts.
  21. *
  22. * The progammer must first create a materialized view that
  23. * will generate count data for a given controlled vocabulary. For example, the Tripal
  24. * Analysis GO creates a materialized view for counting Gene Ontology assignments
  25. * to features. This view is created on install of the module and is named
  26. * 'go_count_analysis'.
  27. *
  28. * Second, the progammer must add an HTML 'div' box to the desired page
  29. * with a class name of 'tripal_cv_tree', and an id of the following format:
  30. *
  31. * tripal_[module_name]_cv_tree_[unique id]
  32. *
  33. * where [module_name] is the name of the tripal module (e.g. tripal_analyisis_go)
  34. * and [unique id] is some unique identifier that the contolling module
  35. * recognizes. This string is the $tree_id variable passed as the first argument
  36. * to the function. For example, the Tripal GO Analysis module generates
  37. * tree ids of the form:
  38. *
  39. * tripal_analysis_go_cv_tree_10_2_bp
  40. *
  41. * In this case the module that will manage this tree is identified as 'tripal_analysis_go' and within
  42. * the [unique id] portion contains the
  43. * organism_id (e.g. 10), analysis_id (e.g. 2) and tree type (bp = biological process).
  44. *
  45. * Second, the programmer must then define a hook in the controlling module for setting
  46. * some options used to build the chart. The hook has the form: hook_cv_tree($tree_id).
  47. * This hook should accept the full $tree_id as the single parameter. For the Tripal
  48. * Analysis GO module the hook is named: tripal_analysis_go_cv_tree.
  49. *
  50. * The array returned by this hook must have the following fields:
  51. * - cv_id
  52. * the cv_id for the controlled vocabulary
  53. * - count_mview
  54. * the name of the materialized view that contains the count data
  55. * this materialized view must have at least two columns, one with the cvterm_id
  56. * for each term and a second column containing the counts. The tree will only
  57. * be expanded to include child terms that have counts.
  58. * - cvterm_id_column
  59. * the column name in the materialized view that contains
  60. * the cvterm_ids
  61. * - count_column
  62. * the column name in the materialized view that contains the
  63. * counts
  64. * - filter
  65. * an SQL compatible WHERE clause string (whithout the word 'WHERE')
  66. * that can be used for filtering the records in the materialized view.
  67. * - label
  68. * the title for the tree
  69. *
  70. * Example from the tripal_analysis_go module:
  71. * @code
  72. * function tripal_analysis_go_cv_tree($tree_id) {
  73. *
  74. * $organism_id = preg_replace("/^tripal_analysis_go_cv_tree_(\d+)-(\d+)_(bp|cc|mf)$/","$1",$tree_id);
  75. * $analysis_id = preg_replace("/^tripal_analysis_go_cv_tree_(\d+)-(\d+)_(bp|cc|mf)$/","$2",$tree_id);
  76. * $type = preg_replace("/^tripal_analysis_go_cv_tree_(\d+)-(\d+)_(bp|cc|mf)$/","$3",$tree_id);
  77. *
  78. * if(strcmp($type,'mf')==0) {
  79. * $class = 'molecular_function';
  80. * }
  81. * if(strcmp($type,'cc')==0) {
  82. * $class = 'cellular_component';
  83. * }
  84. * if(strcmp($type,'bp')==0) {
  85. * $class = 'biological_process';
  86. * }
  87. *
  88. * $options = array(
  89. * cv_id => tripal_cv_get_cv_id($class),
  90. * count_mview => 'go_count_analysis',
  91. * cvterm_id_column => 'cvterm_id',
  92. * count_column => 'feature_count',
  93. * filter => "CNT.organism_id = $organism_id AND CNT.analysis_id = $analysis_id",
  94. * label => 'Features',
  95. * );
  96. * return $options;
  97. * }
  98. *
  99. * @endcode
  100. *
  101. * @param $tree_id
  102. * The unique identifier for the tree
  103. *
  104. * @return
  105. * JSON array needed for the jsTree package for generating expandable trees.
  106. *
  107. * With these three components (materialized view, a 'div' box with proper CSS class and ID, and a hook_cv_tree)
  108. * a tree will be created on the page. There is no need to call this function directly.
  109. *
  110. * @ingroup tripal_cv
  111. */
  112. function tripal_cv_tree($tree_id) {
  113. // parse out the tripal module name from the chart_id to find out
  114. // which Tripal "hook" to call:
  115. $tripal_mod = preg_replace("/^(tripal_.+?)_cv_tree_(.+)$/", "$1", $tree_id);
  116. if ($tripal_mod) {
  117. $callback = $tripal_mod . "_cv_tree";
  118. // now call the function in the module responsible for the tree. This
  119. // should call the tripal_cv_init_cv with the proper parameters set for
  120. // getting the cv_id of the vocabulary to use
  121. $opt = call_user_func_array($callback, array($tree_id));
  122. // we only need to return the cv_id for this function call.
  123. $json_array[] = $opt['cv_id'];
  124. }
  125. $json_array[] = $tree_id;
  126. return drupal_json($json_array);
  127. }
  128. /**
  129. *
  130. * @ingroup tripal_cv
  131. */
  132. function tripal_cv_update_tree() {
  133. $content = array();
  134. $ontology = 'sequence';
  135. // get the id of the term to look up
  136. $cv = check_plain($_REQUEST['cv']);
  137. $term = check_plain($_REQUEST['term']);
  138. $tree_id = check_plain($_REQUEST['tree_id']);
  139. // get the options needed for this tree from the tripal module that
  140. // wants to create the tree
  141. $tripal_mod = preg_replace("/^(tripal_.+?)_cv_tree_(.+)$/", "$1", $tree_id);
  142. if ($tripal_mod) {
  143. $callback = $tripal_mod . "_cv_tree";
  144. $opt = call_user_func_array($callback, array($tree_id));
  145. }
  146. // get the CV root terms
  147. if (strcmp($term, 'root')==0) {
  148. if (!$cv) {
  149. $cv = $opt['cv_id'];
  150. }
  151. $content = tripal_cv_init_tree($cv, $opt['count_mview'],
  152. $opt['cvterm_id_column'], $opt['count_column'], $opt['filter'], $opt['label']);
  153. // get the children terms
  154. }
  155. else {
  156. $content = tripal_cv_get_term_children($term, $opt['count_mview'],
  157. $opt['cvterm_id_column'], $opt['count_column'], $opt['filter'], $opt['label']);
  158. }
  159. drupal_json($content);
  160. }
  161. /**
  162. * Generates JSON needed for jsTree Root-level Branches
  163. *
  164. * This function returns the JSON array for the jsTree
  165. * jQuery code that builds a tree for browsing the ontology. This function
  166. * should be called to generate the root level branches of the tree.
  167. *
  168. * @ingroup tripal_cv
  169. */
  170. function tripal_cv_init_tree($cv_id, $cnt_table = NULL, $fk_column = NULL,
  171. $cnt_column = NULL, $filter = NULL, $label = NULL) {
  172. // get the list of root terms for the provided CV
  173. $sql = "
  174. SELECT *
  175. FROM {cv_root_mview} CRM
  176. WHERE cv_id = %d
  177. ";
  178. $previous_db = tripal_db_set_active('chado');
  179. $results = db_query($sql, $cv_id);
  180. tripal_db_set_active($previous_db);
  181. // prepare the SQL statement that will allow us to pull out count
  182. // information for each term in the tree.
  183. if ($cnt_table) {
  184. if (!$filter) {
  185. $filter = '(1=1)';
  186. }
  187. $cnt_sql = "
  188. SELECT CVT.name, CVT.cvterm_id, CNT.$cnt_column as num_items
  189. FROM {$cnt_table} CNT
  190. INNER JOIN cvterm CVT on CNT.$fk_column = CVT.cvterm_id
  191. WHERE $filter AND CVT.cvterm_id = %d
  192. ORDER BY $cnt_column desc
  193. ";
  194. }
  195. while ($term = db_fetch_object($results)) {
  196. $name = $term->name;
  197. $count = 0;
  198. if ($cnt_table) {
  199. $previous_db = tripal_db_set_active('chado');
  200. $cnt_results = db_query($cnt_sql, $term->cvterm_id);
  201. tripal_db_set_active($previous_db);
  202. while ($cnt = db_fetch_object($cnt_results)) {
  203. $count += $cnt->cnt;
  204. }
  205. if ($count > 0) {
  206. $name .= " ($count $label(s))";
  207. }
  208. }
  209. $content[] = array(
  210. 'attributes' => array(
  211. 'id' => $term->cvterm_id,
  212. ),
  213. 'state' => 'closed',
  214. 'data' => $name,
  215. 'children' => array(),
  216. );
  217. }
  218. return $content;
  219. }
  220. /**
  221. * Generates SON needed for jsTree -expanding a term to view children
  222. *
  223. * This function returns the JSON array for the jsTree
  224. * jQuery code when expanding a term to view it's children.
  225. *
  226. * @ingroup tripal_cv_api
  227. */
  228. function tripal_cv_get_term_children($cvterm_id, $cnt_table = NULL,
  229. $fk_column = NULL, $cnt_column = NULL, $filter = NULL, $label = NULL) {
  230. // get the children for the term provided
  231. $sql = "
  232. SELECT CVTR.cvterm_relationship_id,CVTR.subject_id,
  233. CVT1.name as subject_name, CVT3.name as type_name, CVTR.type_id,
  234. CVT2.name as object_name,CVTR.object_id
  235. FROM {cvterm_relationship} CVTR
  236. INNER JOIN CVTerm CVT1 on CVTR.subject_id = CVT1.cvterm_id
  237. INNER JOIN CVTerm CVT2 on CVTR.object_id = CVT2.cvterm_id
  238. INNER JOIN CVTerm CVT3 on CVTR.type_id = CVT3.cvterm_id
  239. INNER JOIN CV on CV.cv_id = CVT1.cv_id
  240. WHERE CVTR.object_id = %d
  241. ORDER BY CVT1.name
  242. ";
  243. $previous_db = tripal_db_set_active('chado');
  244. $results = db_query($sql, $cvterm_id);
  245. tripal_db_set_active($previous_db);
  246. // prepare the SQL statement that will allow us to pull out count
  247. // information for each term in the tree.
  248. if ($cnt_table) {
  249. if (!$filter) {
  250. $filter = '(1=1)';
  251. }
  252. $cnt_sql = "
  253. SELECT CVT.name, CVT.cvterm_id, CNT.$cnt_column as num_items
  254. FROM {$cnt_table} CNT
  255. INNER JOIN cvterm CVT on CNT.$fk_column = CVT.cvterm_id
  256. WHERE $filter AND CVT.cvterm_id = %d
  257. ORDER BY $cnt_column desc
  258. ";
  259. }
  260. // populate the JSON content array
  261. while ($term = db_fetch_object($results)) {
  262. // count the number of items per term if requested
  263. $name = $term->subject_name;
  264. $count = 0;
  265. if ($cnt_table) {
  266. $previous_db = tripal_db_set_active('chado');
  267. $cnt_results = db_query($cnt_sql, $term->subject_id);
  268. tripal_db_set_active($previous_db);
  269. while ($cnt = db_fetch_object($cnt_results)) {
  270. $count += $cnt->num_items;
  271. }
  272. if ($count > 0) {
  273. $name .= " (" . number_format($count) . " $label)";
  274. // check if we have any children if so then set the value
  275. $previous_db = tripal_db_set_active('chado');
  276. $children = db_fetch_object(db_query($sql, $term->subject_id));
  277. tripal_db_set_active($previous_db);
  278. $state = 'leaf';
  279. if ($children) {
  280. $state = 'closed';
  281. }
  282. $content[] = array(
  283. 'attributes' => array(
  284. 'id' => $term->subject_id,
  285. ),
  286. 'state' => $state,
  287. 'data' => $name,
  288. 'children' => array(),
  289. );
  290. }
  291. }
  292. else {
  293. // check if we have any children if so then set the value
  294. $previous_db = tripal_db_set_active('chado');
  295. $children = db_fetch_object(db_query($sql, $term->subject_id));
  296. tripal_db_set_active($previous_db);
  297. $state = 'leaf';
  298. if ($children) {
  299. $state = 'closed';
  300. }
  301. $content[] = array(
  302. 'attributes' => array(
  303. 'id' => $term->subject_id,
  304. ),
  305. 'state' => $state,
  306. 'data' => $name,
  307. 'children' => array(),
  308. );
  309. }
  310. }
  311. $content[] = $cnt_sql;
  312. return $content;
  313. }
  314. /**
  315. * @todo Stephen: describe what this function does
  316. * @ingroup tripal_cv
  317. */
  318. function tripal_cv_init_browser($cv_id) {
  319. $content = "
  320. <div id=\"tripal_cv_cvterm_info_box\">
  321. <a href=\"#\" onclick=\"$('#tripal_cv_cvterm_info_box').hide()\" style=\"float: right\">Close [X]</a>
  322. <h3>Term Information</h3>
  323. <div id=\"tripal_cv_cvterm_info\"></div>
  324. </div>
  325. <div id=\"tripal_ajaxLoading\" style=\"display:none\">
  326. <div id=\"loadingText\">Loading...</div>
  327. <img src=\"$url\">
  328. </div>
  329. <h3>Tree Browser</h3>
  330. <div id=\"browser\"</div>
  331. </div>
  332. ";
  333. drupal_json(array('update' => "$content"));
  334. }
  335. /**
  336. * Describe a cvterm (Rendered)
  337. *
  338. * @ingroup tripal_cv
  339. */
  340. function tripal_cv_cvterm_info($cvterm_id) {
  341. // get the id of the term to look up
  342. $cv = check_plain($_REQUEST['cv']);
  343. $tree_id = check_plain($_REQUEST['tree_id']);
  344. // first get any additional information to add to the cvterm
  345. if (strcmp($tree_id, 'undefined') != 0) {
  346. $tripal_mod = preg_replace("/^(tripal_.+?)_cv_tree_(.+)$/", "$1", $tree_id);
  347. if ($tripal_mod) {
  348. $callback = $tripal_mod . "_cvterm_add";
  349. $opt = call_user_func_array($callback, array($cvterm_id, $tree_id));
  350. }
  351. }
  352. $sql = "
  353. SELECT CVT.name as cvtermname, CVT.definition, CV.name as cvname,
  354. DBX.accession,DB.urlprefix,DB.db_id,DB.name as dbname
  355. FROM {CVTerm} CVT
  356. INNER JOIN CV on CVT.cv_id = CV.cv_id
  357. INNER JOIN dbxref DBX on CVT.dbxref_id = DBX.dbxref_id
  358. INNER JOIN DB on DBX.db_id = DB.db_id
  359. WHERE CVT.cvterm_id = %d
  360. ";
  361. $previous_db = tripal_db_set_active('chado');
  362. $cvterm = db_fetch_object(db_query($sql, $cvterm_id));
  363. tripal_db_set_active($previous_db);
  364. $sql = "
  365. SELECT CVTS.synonym, CVT.name as cvname
  366. FROM {cvtermsynonym} CVTS
  367. INNER JOIN cvterm CVT on CVTS.type_id = CVT.cvterm_id
  368. WHERE CVTS.cvterm_id = %d
  369. ";
  370. $previous_db = tripal_db_set_active('chado');
  371. $results = db_query($sql, $cvterm_id);
  372. tripal_db_set_active($previous_db);
  373. while ($synonym = db_fetch_object($results)) {
  374. $synonym_rows .= "<b>$synonym->cvname:</b> $synonym->synonym<br />";
  375. }
  376. $accession = $cvterm->accession;
  377. if ($cvterm->urlprefix) {
  378. $accession = "<a href=\"$cvterm->urlprefix$cvterm->accession\">$cvterm->accession</a>";
  379. }
  380. $content = "
  381. <div id=\"cvterm\">
  382. <table>
  383. <tr><th>Term</th><td>$cvterm->cvtermname</td></tr>
  384. <tr><th>Accession</th><td>$accession</td></tr>
  385. <tr><th>Ontology</th><td>$cvterm->cvname</td></tr>
  386. <tr><th>Definition</th><td>$cvterm->definition</td></tr>
  387. <tr><th>Synonyms</th><td>$synonym_rows</td></tr>
  388. <tr><th>Internal ID</th><td>$cvterm_id</td></tr>
  389. ";
  390. // now add in any additional options from a hook
  391. if ($opt) {
  392. foreach ($opt as $key => $value) {
  393. $content .= "<tr><th>$key</th><td>$value</td>";
  394. }
  395. }
  396. // close out the information table
  397. $content .= "
  398. </table>
  399. </div>
  400. ";
  401. drupal_json(array('update' => $content));
  402. }
  403. /**
  404. * Form listing CVs
  405. *
  406. * @ingroup tripal_cv
  407. */
  408. function tripal_cv_list_form($form_state) {
  409. // get a list of db from chado for user to choose
  410. $sql = "
  411. SELECT DISTINCT CV.name,CV.cv_id
  412. FROM {cvterm_relationship} CVTR
  413. INNER JOIN cvterm CVT on CVTR.object_id = CVT.cvterm_id
  414. INNER JOIN CV on CV.cv_id = CVT.cv_id
  415. ";
  416. $previous_db = tripal_db_set_active('chado'); // use chado database
  417. $results = db_query($sql);
  418. tripal_db_set_active($previous_db);
  419. $blastdbs = array();
  420. $cvs[''] = '';
  421. while ($cv = db_fetch_object($results)) {
  422. $cvs[$cv->cv_id] = $cv->name;
  423. }
  424. $form['db_options'] = array(
  425. '#type' => 'value',
  426. '#value' => $cvs
  427. );
  428. $form['cv_list'] = array(
  429. '#title' => t('CVs with relationships'),
  430. '#type' => 'select',
  431. '#description' => t('Choose the controlled vocabulary to browse'),
  432. '#options' => $form['db_options']['#value'],
  433. '#attributes' => array(
  434. 'onChange' => "return tripal_cv_init_browser(this)",
  435. )
  436. );
  437. return $form;
  438. }