tripal_feature.admin.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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'] = $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. drupal_add_js(array('tripalFeature' => array('admin' => array(
  114. 'summary' => $chart,
  115. 'types' => $type_names,
  116. 'organisms' => $organism_names,
  117. 'maxBarHeight' => $max_bar_height,
  118. 'mviewUrl' => url('admin/tripal/schema/mviews/update/' . $mview->mview_id),
  119. 'mviewUable' => $mview->name,
  120. 'mviewLastUpdate' => format_date($mview->last_update),
  121. '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>'.format_date($mview->last_update).'</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>.'
  122. ))), 'setting');
  123. // Finally add all the javascript and css needed to render the chart.
  124. tripal_add_d3js();
  125. drupal_add_css(drupal_get_path('module','tripal_feature') . '/theme/css/tripal_feature.css');
  126. drupal_add_js(drupal_get_path('module','tripal_feature') . '/theme/js/tripalFeature.adminChart.js');
  127. return $output;
  128. }
  129. /**
  130. * Feature Settings page
  131. *
  132. * @ingroup tripal_feature
  133. */
  134. function tripal_feature_admin() {
  135. // FEATURE PAGE TITLES
  136. // Using the Chado Node: Title & Path API
  137. $details = array(
  138. 'module' => 'tripal_feature',
  139. 'content_type' => 'chado_feature',
  140. // An array of options to use under "Page Titles"
  141. // the key should be the token and the value should be the human-readable option
  142. 'options' => array(
  143. '[feature.name]' => 'Feature Name Only',
  144. '[feature.uniquename]' => 'Feature Unique Name Only',
  145. // there should always be one options matching the unique constraint.
  146. '[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'
  147. ),
  148. // the token indicating the unique constraint in the options array
  149. 'unique_option' => '[feature.name], [feature.uniquename] ([feature.type_id>cvterm.name]) [feature.organism_id>organism.genus] [feature.organism_id>organism.species]'
  150. );
  151. // This call adds the configuration form to your current form
  152. // This sub-form handles it's own validation & submit
  153. chado_add_admin_form_set_title($form, $form_state, $details);
  154. // FEATURE NODE URL
  155. // Using the Chado Node: Title & Path API
  156. $details = array(
  157. 'module' => 'tripal_feature',
  158. 'content_type' => 'chado_feature',
  159. // An array of options to use under "Page URL"
  160. // the key should be the token and the value should be the human-readable option
  161. 'options' => array(
  162. '/feature/[feature.feature_id]' => 'Feature ID',
  163. // there should always be one options matching the unique constraint.
  164. '/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'
  165. )
  166. );
  167. // This call adds the configuration form to your current form
  168. // This sub-form handles it's own validation & submit
  169. chado_add_admin_form_set_url($form, $form_state, $details);
  170. // FEATURE BROWSER
  171. $form['browser'] = array(
  172. '#type' => 'fieldset',
  173. '#title' => t('Feature Browser'),
  174. '#collapsible' => TRUE,
  175. '#collapsed' => TRUE,
  176. );
  177. $form['browser']['browser_desc'] = array(
  178. '#markup' => t('A feature browser can be added to an organism page to allow users to quickly ' .
  179. 'access a feature. This will most likely not be the ideal mechanism for accessing feature ' .
  180. 'information, especially for large sites, but it will alow users exploring the site (such ' .
  181. 'as students) to better understand the data types available on the site.'),
  182. );
  183. $form['browser']['feature_types'] = array(
  184. '#title' => t('Feature Types'),
  185. '#type' => 'textarea',
  186. '#description' => t("Enter the Sequence Ontology (SO) terms for the feature types that " .
  187. "will be shown in the feature browser."),
  188. '#default_value' => variable_get('chado_browser_feature_types', 'gene mRNA'),
  189. );
  190. $form['browser']['set_browse_button'] = array(
  191. '#type' => 'submit',
  192. '#value' => t('Set Browser'),
  193. '#weight' => 2,
  194. );
  195. // FEATURE SUMMARY REPORT
  196. $form['summary'] = array(
  197. '#type' => 'fieldset',
  198. '#title' => t('Feature Summary Report'),
  199. '#collapsible' => TRUE,
  200. '#collapsed' => TRUE,
  201. );
  202. $form['summary']['feature_mapping'] = array(
  203. '#title' => 'Map feature types',
  204. '#description' => t('You may specify which Sequence Ontology (SO) terms to show in the ' .
  205. 'feature summary report by listing them in the following text area. Enter one per line. ' .
  206. 'If left blank, all SO terms for all features will be shown in the report. Only those terms ' .
  207. 'listed below will be shown in the report. Terms will appear in the report in the same order listed. To rename a ' .
  208. 'SO term to be more human readable form, use an \'=\' sign after the SO term (e.g. \'polypeptide = Protein\')'),
  209. '#type' => 'textarea',
  210. '#rows' => 15,
  211. '#default_value' => variable_get('tripal_feature_summary_report_mapping', ''),
  212. );
  213. $form['summary']['set_summary_button'] = array(
  214. '#type' => 'submit',
  215. '#value' => t('Set Summary'),
  216. '#weight' => 2,
  217. );
  218. return system_settings_form($form);
  219. }
  220. /**
  221. * Validate the feature settings forms
  222. *
  223. * @ingroup tripal_feature
  224. */
  225. function tripal_feature_admin_validate($form, &$form_state) {
  226. global $user; // we need access to the user info
  227. $job_args = array();
  228. variable_set('chado_browser_feature_types', $form_state['values']['feature_types']);
  229. switch ($form_state['values']['op']) {
  230. case t('Set Summary') :
  231. variable_set('tripal_feature_summary_report_mapping', $form_state['values']['feature_mapping']);
  232. break;
  233. }
  234. }
  235. /**
  236. * USort function for the admin summary chart.
  237. * Not meant to be called directly.
  238. */
  239. function tripal_feature_admin_summary_sort($a, $b) {
  240. if ($a['total_features'] == $b['total_features']) return 0;
  241. return $b['total_features'] - $a['total_features'];
  242. }