tripal_feature.admin.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. /**
  3. * @file
  4. * Administration of features
  5. */
  6. /**
  7. * Launchpad for feature administration.
  8. *
  9. * @ingroup tripal_feature
  10. */
  11. function tripal_feature_admin_feature_view() {
  12. $output = '';
  13. // set the breadcrumb
  14. $breadcrumb = array();
  15. $breadcrumb[] = l('Home', '<front>');
  16. $breadcrumb[] = l('Administration', 'admin');
  17. $breadcrumb[] = l('Tripal', 'admin/tripal');
  18. $breadcrumb[] = l('Chado', 'admin/tripal/chado');
  19. $breadcrumb[] = l('Features', 'admin/tripal/chado/tripal_feature');
  20. drupal_set_breadcrumb($breadcrumb);
  21. // Add the view
  22. $view = views_embed_view('tripal_feature_admin_features','default');
  23. if (isset($view)) {
  24. $output .= $view;
  25. }
  26. else {
  27. $output .= '<p>The Feature module uses primarily views to provide an '
  28. . 'administrative interface. Currently one or more views needed for this '
  29. . 'administrative interface are disabled. <strong>Click each of the following links to '
  30. . 'enable the pertinent views</strong>:</p>';
  31. $output .= '<ul>';
  32. $output .= '<li>'.l('Features View', 'admin/tripal/chado/tripal_feature/views/features/enable').'</li>';
  33. $output .= '</ul>';
  34. }
  35. // Add a summary chart.
  36. //-----------------------------------
  37. // We are using the organism_feature_count materialized view as the source for our data.
  38. // Thus grab all the records from this materialized view.
  39. $organism_feature_count = chado_select_record(
  40. 'organism_feature_count',
  41. array('*'),
  42. array(),
  43. array('order_by' => array('genus' => 'ASC', 'species' => 'ASC', 'feature_type' => 'ASC', 'num_features' => 'DESC'))
  44. );
  45. // Initialize variables.
  46. $chart = array();
  47. $type_names = array();
  48. $organism_names = array();
  49. $max_bar_height = 0;
  50. // Process each row of the materialzied view into the chart array.
  51. // Note: it's first keyed by type since each type will be a bar. Each type will have
  52. // a "bars" array with the start (y0) and end (y1) height on the bar for a given
  53. // organism. Finally we keep a record of the names of the types & organisms
  54. // for axis' and legend generation respectively.
  55. foreach ($organism_feature_count as $row) {
  56. // Build up the easy details for the current row's type. These will be overridden
  57. // multiple times but that's more efficient than checking each time.
  58. $chart[$row->cvterm_id]['cvterm_id'] = $row->cvterm_id;
  59. $chart[$row->cvterm_id]['name'] = str_replace('_', ' ', $row->feature_type);
  60. // Save the name of the type and organism into their respective arrays
  61. // for generation of axis' and legends for the chart.
  62. $type_names[$row->cvterm_id] = $row->feature_type;
  63. $organism_names[$row->organism_id] = $row->genus . ' ' . $row->species;
  64. // Save information about the current organism. This isn't actually used by the
  65. // chart but can be used to debug the bar generation to follow.
  66. $chart[$row->cvterm_id]['organisms'][] = array(
  67. 'name' => $row->genus . ' ' . $row->species,
  68. 'value' => (int) $row->num_features
  69. );
  70. // Now to build the bar array with the start (y0) and end (y1) height on the
  71. // bar for a given organism.
  72. // NOTE: we cannot assume the types are all in order so store y0 & y1 in the
  73. // $chart[type] array.
  74. // If y0 has not yet been set for this type then we're starting with the first
  75. // chunk (organism) on the bar.
  76. if (!isset($chart[$row->cvterm_id]['y0'])) {
  77. $chart[$row->cvterm_id]['y0'] = 0;
  78. $chart[$row->cvterm_id]['y1'] = $row->num_features;
  79. }
  80. // Otherwise, add the next chunk (organism) on top of the pre-existing bar.
  81. else {
  82. $chart[$row->cvterm_id]['y0'] = $chart[$row->cvterm_id]['y1'];
  83. $chart[$row->cvterm_id]['y1'] = $chart[$row->cvterm_id]['y0'] + $row->num_features;
  84. }
  85. // Now save the bar chunk we just determined.
  86. $chart[$row->cvterm_id]['bars'][] = array(
  87. 'name' => $row->genus . ' ' . $row->species,
  88. 'y0' => $chart[$row->cvterm_id]['y0'],
  89. 'y1' => $chart[$row->cvterm_id]['y1'],
  90. );
  91. // We also need to keep track of the total number of features for a single bar (Type).
  92. $chart[$row->cvterm_id]['total_features'] = $chart[$row->cvterm_id]['y1'];
  93. // And the maximum "height" for all bars.
  94. if ($max_bar_height < $chart[$row->cvterm_id]['total_features']) {
  95. $max_bar_height = $chart[$row->cvterm_id]['total_features'];
  96. }
  97. }
  98. // Sort based on the total number of features.
  99. // NOTE: This changes the keys so it's no longer the organism/type_id.
  100. usort($chart, 'tripal_feature_admin_summary_sort');
  101. sort($type_names);
  102. sort($organism_names);
  103. // We also need to add information about the materialized views
  104. // so that admin can update it and know how recent the data is.
  105. $mview = db_query('
  106. SELECT mview_id, name, last_update
  107. FROM tripal_mviews
  108. WHERE mv_table=:mv_table',
  109. array(':mv_table' => 'organism_feature_count')
  110. )->fetchObject();
  111. // Save everything we just determined as a Drupal JS settings so that we have access to
  112. // it in our js script.
  113. $last_updated = $mview->last_update ? format_date($mview->last_update) : '';
  114. drupal_add_js(array('tripalFeature' => array('admin' => array(
  115. 'summary' => $chart,
  116. 'types' => $type_names,
  117. 'organisms' => $organism_names,
  118. 'maxBarHeight' => $max_bar_height,
  119. 'mviewUrl' => url('admin/tripal/schema/mviews/update/' . $mview->mview_id),
  120. 'mviewUable' => $mview->name,
  121. 'mviewLastUpdate' => $last_updated,
  122. 'figureDesc' => '<span class="figure-title">Feature Composition</span>: This figure depicts the type and source organism of features in your Tripal site. It is populated from the <em>'.$mview->name.'</em> materialized view which was last updated on <em>'.$last_updated.'</em>. <strong><em>To update this chart, <a href="'.url('admin/tripal/schema/mviews/update/' . $mview->mview_id).'">submit a job to update the materialized view</a></em></strong>.'
  123. ))), 'setting');
  124. // Finally add all the javascript and css needed to render the chart.
  125. tripal_add_d3js();
  126. drupal_add_css(drupal_get_path('module','tripal_feature') . '/theme/css/tripal_feature.css');
  127. drupal_add_js(drupal_get_path('module','tripal_feature') . '/theme/js/tripalFeature.adminChart.js');
  128. return $output;
  129. }
  130. /**
  131. * Feature Settings page
  132. *
  133. * @ingroup tripal_feature
  134. */
  135. function tripal_feature_admin() {
  136. // FEATURE PAGE TITLES
  137. // Using the Chado Node: Title & Path API
  138. $details = array(
  139. 'module' => 'tripal_feature',
  140. 'content_type' => 'chado_feature',
  141. // An array of options to use under "Page Titles"
  142. // the key should be the token and the value should be the human-readable option
  143. 'options' => array(
  144. '[feature.name]' => 'Feature Name Only',
  145. '[feature.uniquename]' => 'Feature Unique Name Only',
  146. // there should always be one options matching the unique constraint.
  147. '[feature.name], [feature.uniquename] ([feature.type_id>cvterm.name]) [feature.organism_id>organism.genus] [feature.organism_id>organism.species]' => 'Unique Contraint: Includes the name, uniquename, type and scientific name'
  148. ),
  149. // the token indicating the unique constraint in the options array
  150. 'unique_option' => '[feature.name], [feature.uniquename] ([feature.type_id>cvterm.name]) [feature.organism_id>organism.genus] [feature.organism_id>organism.species]'
  151. );
  152. // This call adds the configuration form to your current form
  153. // This sub-form handles it's own validation & submit
  154. chado_add_admin_form_set_title($form, $form_state, $details);
  155. // FEATURE NODE URL
  156. // Using the Chado Node: Title & Path API
  157. $details = array(
  158. 'module' => 'tripal_feature',
  159. 'content_type' => 'chado_feature',
  160. // An array of options to use under "Page URL"
  161. // the key should be the token and the value should be the human-readable option
  162. 'options' => array(
  163. '/feature/[feature.feature_id]' => 'Feature ID',
  164. // there should always be one options matching the unique constraint.
  165. '/feature/[feature.organism_id>organism.genus]/[feature.organism_id>organism.species]/[feature.type_id>cvterm.name]/[feature.uniquename]' => 'Unique Contraint: Includes the name, uniquename, type and scientific name'
  166. )
  167. );
  168. // This call adds the configuration form to your current form
  169. // This sub-form handles it's own validation & submit
  170. chado_add_admin_form_set_url($form, $form_state, $details);
  171. // FEATURE BROWSER
  172. $form['browser'] = array(
  173. '#type' => 'fieldset',
  174. '#title' => t('Feature Browser'),
  175. '#collapsible' => TRUE,
  176. '#collapsed' => TRUE,
  177. );
  178. $form['browser']['browser_desc'] = array(
  179. '#markup' => t('A feature browser can be added to an organism page to allow users to quickly ' .
  180. 'access a feature. This will most likely not be the ideal mechanism for accessing feature ' .
  181. 'information, especially for large sites, but it will alow users exploring the site (such ' .
  182. 'as students) to better understand the data types available on the site.'),
  183. );
  184. $form['browser']['feature_types'] = array(
  185. '#title' => t('Feature Types'),
  186. '#type' => 'textarea',
  187. '#description' => t("Enter the Sequence Ontology (SO) terms for the feature types that " .
  188. "will be shown in the feature browser."),
  189. '#default_value' => variable_get('chado_browser_feature_types', 'gene mRNA'),
  190. );
  191. $form['browser']['set_browse_button'] = array(
  192. '#type' => 'submit',
  193. '#value' => t('Set Browser'),
  194. '#weight' => 2,
  195. );
  196. // FEATURE SUMMARY REPORT
  197. $form['summary'] = array(
  198. '#type' => 'fieldset',
  199. '#title' => t('Feature Summary Report'),
  200. '#collapsible' => TRUE,
  201. '#collapsed' => TRUE,
  202. );
  203. $form['summary']['feature_mapping'] = array(
  204. '#title' => 'Map feature types',
  205. '#description' => t('You may specify which Sequence Ontology (SO) terms to show in the ' .
  206. 'feature summary report by listing them in the following text area. Enter one per line. ' .
  207. 'If left blank, all SO terms for all features will be shown in the report. Only those terms ' .
  208. 'listed below will be shown in the report. Terms will appear in the report in the same order listed. To rename a ' .
  209. 'SO term to be more human readable form, use an \'=\' sign after the SO term (e.g. \'polypeptide = Protein\')'),
  210. '#type' => 'textarea',
  211. '#rows' => 15,
  212. '#default_value' => variable_get('tripal_feature_summary_report_mapping', ''),
  213. );
  214. $form['summary']['set_summary_button'] = array(
  215. '#type' => 'submit',
  216. '#value' => t('Set Summary'),
  217. '#weight' => 2,
  218. );
  219. return system_settings_form($form);
  220. }
  221. /**
  222. * Validate the feature settings forms
  223. *
  224. * @ingroup tripal_feature
  225. */
  226. function tripal_feature_admin_validate($form, &$form_state) {
  227. global $user; // we need access to the user info
  228. $job_args = array();
  229. variable_set('chado_browser_feature_types', $form_state['values']['feature_types']);
  230. switch ($form_state['values']['op']) {
  231. case t('Set Summary') :
  232. variable_set('tripal_feature_summary_report_mapping', $form_state['values']['feature_mapping']);
  233. break;
  234. }
  235. }
  236. /**
  237. * USort function for the admin summary chart.
  238. * Not meant to be called directly.
  239. */
  240. function tripal_feature_admin_summary_sort($a, $b) {
  241. if ($a['total_features'] == $b['total_features']) return 0;
  242. return $b['total_features'] - $a['total_features'];
  243. }