tripal_cv.obo_loader.inc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254
  1. <?php
  2. /**
  3. * @file
  4. * Functions to aid in loading ontologies into the chado cv module
  5. */
  6. /**
  7. * @defgroup tripal_obo_loader Ontology Loader
  8. * @ingroup tripal_cv
  9. * @{
  10. * Functions to aid in loading ontologies into the chado cv module
  11. * @}
  12. */
  13. /**
  14. * Provides the form to load an already existing controlled
  15. * Vocabulary into chado
  16. *
  17. * @param $form
  18. * The form array
  19. * @param $form_state
  20. * The form state array
  21. *
  22. * @return
  23. * The form array with new additions
  24. *
  25. * @ingroup tripal_obo_loader
  26. */
  27. function tripal_cv_obo_form($form, &$form_state) {
  28. // get a list of db from chado for user to choose
  29. $sql = "SELECT * FROM {tripal_cv_obo} ORDER BY name";
  30. $results = db_query($sql);
  31. $obos = array();
  32. $obos[] = '';
  33. foreach ($results as $obo) {
  34. // $obos[$obo->obo_id] = "$obo->name | $obo->path";
  35. $obos[$obo->obo_id] = $obo->name;
  36. }
  37. $form['obo_existing'] = array(
  38. '#type' => 'fieldset',
  39. '#title' => t('Use a Saved Ontology OBO Reference')
  40. );
  41. $form['obo_new'] = array(
  42. '#type' => 'fieldset',
  43. '#title' => t('Use a New Ontology OBO Reference')
  44. );
  45. $form['obo_existing']['existing_instructions']= array(
  46. '#value' => t('The Ontology OBO files listed in the drop down below have been automatically added upon
  47. installation of the Tripal CV module or were added from a previous upload. Select
  48. an OBO, then click the submit button to load the vocabulary into the database. If the
  49. vocabularies already exist then the ontology will be updated.'),
  50. );
  51. $form['obo_existing']['obo_id'] = array(
  52. '#title' => t('Ontology OBO File Reference'),
  53. '#type' => 'select',
  54. '#options' => $obos,
  55. );
  56. $form['obo_new']['path_instructions']= array(
  57. '#value' => t('Provide the name and path for the OBO file. If the vocabulary OBO file
  58. is stored local to the server provide a file name. If the vocabulry is stored remotely,
  59. provide a URL. Only provide a URL or a local file, not both.'),
  60. );
  61. $form['obo_new']['obo_name']= array(
  62. '#type' => 'textfield',
  63. '#title' => t('New Vocabulary Name'),
  64. '#description' => t('Please provide a name for this vocabulary. After upload, this name will appear in the drop down
  65. list above for use again later.'),
  66. );
  67. $form['obo_new']['obo_url']= array(
  68. '#type' => 'textfield',
  69. '#title' => t('Remote URL'),
  70. '#description' => t('Please enter a URL for the online OBO file. The file will be downloaded and parsed.
  71. (e.g. http://www.obofoundry.org/ro/ro.obo'),
  72. );
  73. $form['obo_new']['obo_file']= array(
  74. '#type' => 'textfield',
  75. '#title' => t('Local File'),
  76. '#description' => t('Please enter the full system path for an OBO definition file, or a path within the Drupal
  77. installation (e.g. /sites/default/files/xyz.obo). The path must be accessible to the
  78. server on which this Drupal instance is running.'),
  79. );
  80. $form['submit'] = array(
  81. '#type' => 'submit',
  82. '#value' => t('Submit'),
  83. '#executes_submit_callback' => TRUE,
  84. );
  85. $form['#redirect'] = 'admin/tripal/tripal_cv/obo_loader';
  86. return $form;
  87. }
  88. /**
  89. * The submit function for the load ontology form. It registers a
  90. * tripal job to import the user specified ontology file
  91. *
  92. * @param $form
  93. * The form array
  94. * @param $form_state
  95. * The form state array
  96. *
  97. *
  98. * @ingroup tripal_obo_loader
  99. */
  100. function tripal_cv_obo_form_submit($form, &$form_state) {
  101. $obo_id = $form_state['values']['obo_id'];
  102. $obo_name = trim($form_state['values']['obo_name']);
  103. $obo_url = trim($form_state['values']['obo_url']);
  104. $obo_file = trim($form_state['values']['obo_file']);
  105. tripal_submit_obo_job(array(
  106. 'obo_id' => $obo_id,
  107. 'name' => $obo_name,
  108. 'url' => $obo_url,
  109. 'file' => $obo_file
  110. ));
  111. }
  112. /**
  113. * A wrapper function for importing the user specified OBO file into Chado by
  114. * specifying the obo_id of the OBO. It requires that the file be in OBO v1.2
  115. * compatible format. This function is typically executed via the Tripal jobs
  116. * management after a user submits a job via the Load Onotloies form.
  117. *
  118. * @param $obo_id
  119. * An obo_id from the tripal_cv_obo file that specifies which OBO file to import
  120. * @param $job_id
  121. * The job_id of the job from the Tripal jobs management system.
  122. *
  123. * @ingroup tripal_obo_loader
  124. */
  125. function tripal_cv_load_obo_v1_2_id($obo_id, $jobid = NULL) {
  126. // get the OBO reference
  127. $sql = "SELECT * FROM {tripal_cv_obo} WHERE obo_id = :obo_id";
  128. $obo = db_query($sql, array(':obo_id' => $obo_id))->fetchObject();
  129. // if the reference is for a remote URL then run the URL processing function
  130. if (preg_match("/^http:\/\//", $obo->path) or preg_match("/^ftp:\/\//", $obo->path)) {
  131. tripal_cv_load_obo_v1_2_url($obo->name, $obo->path, $jobid, 0);
  132. }
  133. // if the reference is for a local file then run the file processing function
  134. else {
  135. // check to see if the file is located local to Drupal
  136. $dfile = $_SERVER['DOCUMENT_ROOT'] . base_path() . $obo->path;
  137. if (file_exists($dfile)) {
  138. tripal_cv_load_obo_v1_2_file($obo->name, $dfile , $jobid, 0);
  139. }
  140. // if not local to Drupal, the file must be someplace else, just use
  141. // the full path provided
  142. else {
  143. if (file_exists($obo->path)) {
  144. tripal_cv_load_obo_v1_2_file($obo->name, $obo->path, $jobid, 0);
  145. }
  146. else {
  147. print "ERROR: counld not find OBO file: '$obo->path'\n";
  148. }
  149. }
  150. }
  151. }
  152. /**
  153. * A wrapper function for importing the user specified OBO file into Chado by
  154. * specifying the filename and path of the OBO. It requires that the file be in OBO v1.2
  155. * compatible format. This function is typically executed via the Tripal jobs
  156. * management after a user submits a job via the Load Onotloies form.
  157. *
  158. * @param $obo_name
  159. * The name of the OBO (typially the ontology or controlled vocabulary name)
  160. * @param $file
  161. * The path on the file system where the ontology can be found
  162. * @param $job_id
  163. * The job_id of the job from the Tripal jobs management system.
  164. * @param $is_new
  165. * Set to TRUE if this is a new ontology that does not yet exist in the
  166. * tripal_cv_obo table. If TRUE the OBO will be added to the table.
  167. *
  168. * @ingroup tripal_obo_loader
  169. */
  170. function tripal_cv_load_obo_v1_2_file($obo_name, $file, $jobid = NULL, $is_new = TRUE) {
  171. $newcvs = array();
  172. if ($is_new) {
  173. tripal_insert_obo($obo_name, $file);
  174. }
  175. $success = tripal_cv_load_obo_v1_2($file, $jobid, $newcvs);
  176. if ($success) {
  177. // update the cvtermpath table
  178. tripal_cv_load_update_cvtermpath($newcvs, $jobid);
  179. print "\nDone\n";
  180. }
  181. }
  182. /**
  183. * A wrapper function for importing the user specified OBO file into Chado by
  184. * specifying the remote URL of the OBO. It requires that the file be in OBO v1.2
  185. * compatible format. This function is typically executed via the Tripal jobs
  186. * management after a user submits a job via the Load Onotloies form.
  187. *
  188. * @param $obo_name
  189. * The name of the OBO (typially the ontology or controlled vocabulary name)
  190. * @param $url
  191. * The remote URL of the OBO file.
  192. * @param $job_id
  193. * The job_id of the job from the Tripal jobs management system.
  194. * @param $is_new
  195. * Set to TRUE if this is a new ontology that does not yet exist in the
  196. * tripal_cv_obo table. If TRUE the OBO will be added to the table.
  197. *
  198. * @ingroup tripal_obo_loader
  199. */
  200. function tripal_cv_load_obo_v1_2_url($obo_name, $url, $jobid = NULL, $is_new = TRUE) {
  201. $newcvs = array();
  202. // first download the OBO
  203. $temp = tempnam(sys_get_temp_dir(), 'obo_');
  204. print "Downloading URL $url, saving to $temp\n";
  205. $url_fh = fopen($url, "r");
  206. $obo_fh = fopen($temp, "w");
  207. if (!$url_fh) {
  208. tripal_cv_obo_quiterror("Unable to download the remote OBO file at $url. Could a firewall be blocking outgoing connections? " .
  209. " if you are unable to download the file you may manually downlod the OBO file and use the web interface to " .
  210. " specify the location of the file on your server.");
  211. }
  212. while (!feof($url_fh)) {
  213. fwrite($obo_fh, fread($url_fh, 255), 255);
  214. }
  215. fclose($url_fh);
  216. fclose($obo_fh);
  217. if ($is_new) {
  218. tripal_insert_obo($obo_name, $url);
  219. }
  220. // second, parse the OBO
  221. $success = tripal_cv_load_obo_v1_2($temp, $jobid, $newcvs);
  222. if ($success) {
  223. // update the cvtermpath table
  224. tripal_cv_load_update_cvtermpath($newcvs, $jobid);
  225. print "Done\n";
  226. }
  227. // now remove the temp file
  228. unlink($temp);
  229. }
  230. /**
  231. * A function for executing the cvtermpath function of Chado. This function
  232. * populates the cvtermpath table of Chado for quick lookup of term
  233. * relationships
  234. *
  235. * @param $newcvs
  236. * An associative array of controlled vocabularies to update. The key must be
  237. * the name of the vocabulary and the value the cv_id from the cv table of chado.
  238. * @param $jobid
  239. * The job_id of the job from the Tripal jobs management system.
  240. *
  241. * @ingroup tripal_obo_loader
  242. */
  243. function tripal_cv_load_update_cvtermpath($newcvs, $jobid) {
  244. print "\nUpdating cvtermpath table. This may take a while...\n";
  245. foreach ($newcvs as $namespace => $cvid) {
  246. tripal_update_cvtermpath($cvid, $jobid);
  247. }
  248. }
  249. /**
  250. * Imports a given OBO file into Chado. This function is usually called by
  251. * one of three wrapper functions: tripal_cv_load_obo_v1_2_id,
  252. * tripal_cv_load_obo_v1_2_file or tirpal_cv_load_obo_v1_2_url. But, it can
  253. * be called directly if the full path to an OBO file is available on the
  254. * file system.
  255. *
  256. * @param $flie
  257. * The full path to the OBO file on the file system
  258. * @param $jobid
  259. * The job_id of the job from the Tripal jobs management system.
  260. * @param $newcvs
  261. * An empty array passed by reference that upon return will contain the list
  262. * of newly added vocabularies. The key will contain the CV name and the
  263. * value the new cv_id
  264. *
  265. *
  266. * @ingroup tripal_obo_loader
  267. */
  268. function tripal_cv_load_obo_v1_2($file, $jobid = NULL, &$newcvs) {
  269. $transaction = db_transaction();
  270. print "\nNOTE: Loading of this OBO file is performed using a database transaction. \n" .
  271. "If the load fails or is terminated prematurely then the entire set of \n" .
  272. "insertions/updates is rolled back and will not be found in the database\n\n";
  273. try {
  274. $header = array();
  275. // make sure our temporary table exists
  276. $ret = array();
  277. // empty the temp table
  278. $sql = "DELETE FROM {tripal_obo_temp}";
  279. chado_query($sql);
  280. print "Step 1: Preloading File $file\n";
  281. // make sure we have an 'internal' and a '_global' database
  282. if (!tripal_insert_db(array('name' => 'internal'))) {
  283. tripal_cv_obo_quiterror("Cannot add 'internal' database");
  284. }
  285. if (!tripal_insert_db(array('name' => '_global'))) {
  286. tripal_cv_obo_quiterror("Cannot add '_global' database");
  287. }
  288. // parse the obo file
  289. $default_db = tripal_cv_obo_parse($file, $header, $jobid);
  290. // add the CV for this ontology to the database. The v1.2 definition
  291. // specifies a 'default-namespace' to be used if a 'namespace' is not
  292. // present for each stanza. Some ontologies have adopted the v1.4 method
  293. // in their v1.2 files and not including it.
  294. if (array_key_exists('default-namespace', $header)) {
  295. $defaultcv = tripal_insert_cv($header['default-namespace'][0], '');
  296. if (!$defaultcv) {
  297. tripal_cv_obo_quiterror('Cannot add namespace ' . $header['default-namespace'][0]);
  298. }
  299. $newcvs[$header['default-namespace'][0]] = $defaultcv->cv_id;
  300. }
  301. // if the 'default-namespace' is missing
  302. else {
  303. // look to see if an 'ontology' key is present. It is part of the v1.4
  304. // specification so it shouldn't be in the file, but just in case
  305. if (array_key_exists('ontology', $header)) {
  306. $defaultcv = tripal_insert_cv(strtoupper($header['ontology'][0]), '');
  307. if (!$defaultcv) {
  308. tripal_cv_obo_quiterror('Cannot add namespace ' . strtoupper($header['ontology'][0]));
  309. }
  310. $newcvs[strtoupper(strtoupper($header['ontology'][0]))] = $defaultcv->cv_id;
  311. }
  312. else {
  313. $defaultcv = tripal_insert_cv('_global', '');
  314. $newcvs['_global'] = $defaultcv->cv_id;
  315. }
  316. watchdog('t_obo_loader', "This OBO is missing the 'default-namespace' header. It is not possible to determine which vocabulary terms without a 'namespace' key should go. Instead, those terms will be placed in the '%vocab' vocabulary.",
  317. array('%vocab' => $defaultcv->name), WATCHDOG_WARNING);
  318. }
  319. // add any typedefs to the vocabulary first
  320. print "\nStep 2: Loading type defs...\n";
  321. tripal_cv_obo_load_typedefs($defaultcv, $newcvs, $default_db, $jobid);
  322. // next add terms to the vocabulary
  323. print "\nStep 3: Loading terms...\n";
  324. if (!tripal_cv_obo_process_terms($defaultcv, $jobid, $newcvs, $default_db)) {
  325. tripal_cv_obo_quiterror('Cannot add terms from this ontology');
  326. }
  327. }
  328. catch (Exception $e) {
  329. $transaction->rollback();
  330. print "\n"; // make sure we start errors on new line
  331. print "FAILED. Rolling back database changes...\n";
  332. watchdog_exception('T_obo_loader', $e);
  333. return FALSE;
  334. }
  335. return TRUE;
  336. }
  337. /**
  338. * Immediately terminates loading of the OBO file.
  339. *
  340. * @param $message
  341. * The error message to present to the user
  342. *
  343. * @ingroup tripal_obo_loader
  344. */
  345. function tripal_cv_obo_quiterror($message) {
  346. tripal_report_error("T_obo_loader", TRIPAL_ERROR, $message, array());
  347. exit;
  348. }
  349. /**
  350. * OBO files are divided into a typedefs terms section and vocabulary terms section.
  351. * This function loads the typedef terms from the OBO.
  352. *
  353. * @param $defaultcv
  354. * A database object containing a record from the cv table for the
  355. * default controlled vocabulary
  356. * @param $newcvs
  357. * An associative array of controlled vocabularies for this OBO. The key must be
  358. * the name of the vocabulary and the value the cv_id from the cv table of chado.
  359. * @param $default_db
  360. * The name of the default database.
  361. * @param $jobid
  362. * The job_id of the job from the Tripal jobs management system.
  363. *
  364. * @ingroup tripal_obo_loader
  365. */
  366. function tripal_cv_obo_load_typedefs($defaultcv, $newcvs, $default_db, $jobid) {
  367. $sql = "SELECT * FROM {tripal_obo_temp} WHERE type = 'Typedef' ";
  368. $typedefs = chado_query($sql);
  369. $sql = "
  370. SELECT count(*) as num_terms
  371. FROM {tripal_obo_temp}
  372. WHERE type = 'Typedef'
  373. ";
  374. $result = chado_query($sql)->fetchObject();
  375. $count = $result->num_terms;
  376. // calculate the interval for updates
  377. $interval = intval($count * 0.0001);
  378. if ($interval < 1) {
  379. $interval = 1;
  380. }
  381. $i = 0;
  382. foreach ($typedefs as $typedef) {
  383. $term = unserialize(base64_decode($typedef->stanza));
  384. // update the job status every interval
  385. if ($jobid and $i % $interval == 0) {
  386. $complete = ($i / $count) * 33.33333333;
  387. tripal_set_job_progress($jobid, intval($complete + 33.33333333));
  388. printf("%d of %d records. (%0.2f%%) Memory: %s bytes\r", $i, $count, $complete * 3, number_format(memory_get_usage()));
  389. }
  390. tripal_cv_obo_process_term($term, $defaultcv->name, 1, $newcvs, $default_db);
  391. $i++;
  392. }
  393. // set the final status
  394. if ($jobid) {
  395. if ($count > 0) {
  396. $complete = ($i / $count) * 33.33333333;
  397. }
  398. else {
  399. $complete = 33.33333333;
  400. }
  401. tripal_set_job_progress($jobid, intval($complete + 33.33333333));
  402. printf("%d of %d records. (%0.2f%%) Memory: %s bytes\r", $i, $count, $complete * 3, number_format(memory_get_usage()));
  403. }
  404. return 1;
  405. }
  406. /**
  407. * OBO files are divided into a typedefs section and a terms section. This
  408. * function loads the typedef terms from the OBO.
  409. *
  410. * @param $defaultcv
  411. * A database object containing a record from the cv table for the
  412. * default controlled vocabulary
  413. * @param $jobid
  414. * The job_id of the job from the Tripal jobs management system.
  415. * @param $newcvs
  416. * An associative array of controlled vocabularies for this OBO. The key must be
  417. * the name of the vocabulary and the value the cv_id from the cv table of chado.
  418. * @param $default_db
  419. * The name of the default database.
  420. * @ingroup tripal_obo_loader
  421. */
  422. function tripal_cv_obo_process_terms($defaultcv, $jobid = NULL, &$newcvs, $default_db) {
  423. $i = 0;
  424. // iterate through each term from the OBO file and add it
  425. $sql = "
  426. SELECT * FROM {tripal_obo_temp}
  427. WHERE type = 'Term'
  428. ORDER BY id
  429. ";
  430. $terms = chado_query($sql);
  431. $sql = "
  432. SELECT count(*) as num_terms
  433. FROM {tripal_obo_temp}
  434. WHERE type = 'Term'
  435. ";
  436. $result = chado_query($sql)->fetchObject();
  437. $count = $result->num_terms;
  438. // calculate the interval for updates
  439. $interval = intval($count * 0.0001);
  440. if ($interval < 1) {
  441. $interval = 1;
  442. }
  443. foreach ($terms as $t) {
  444. $term = unserialize(base64_decode($t->stanza));
  445. // update the job status every interval
  446. if ($jobid and $i % $interval == 0) {
  447. $complete = ($i / $count) * 33.33333333;
  448. tripal_set_job_progress($jobid, intval($complete + 66.666666));
  449. printf("%d of %d records. (%0.2f%%) Memory: %s bytes\r", $i, $count, $complete * 3, number_format(memory_get_usage()));
  450. }
  451. // add/update this term
  452. if (!tripal_cv_obo_process_term($term, $defaultcv->name, 0, $newcvs, $default_db)) {
  453. tripal_cv_obo_quiterror("Failed to process terms from the ontology");
  454. }
  455. $i++;
  456. }
  457. // set the final status
  458. if ($jobid) {
  459. if ($count > 0) {
  460. $complete = ($i / $count) * 33.33333333;
  461. }
  462. else {
  463. $complete = 33.33333333;
  464. }
  465. tripal_set_job_progress($jobid, intval($complete + 66.666666));
  466. printf("%d of %d records. (%0.2f%%) Memory: %s bytes\r", $i, $count, $complete * 3, number_format(memory_get_usage()));
  467. }
  468. return 1;
  469. }
  470. /**
  471. * Uses the provided term array to add/update information to Chado about the
  472. * term including the term, dbxref, synonyms, properties, and relationships.
  473. *
  474. * @param $term
  475. * An array representing the cvterm.
  476. * @param $defaultcv
  477. * The name of the default controlled vocabulary
  478. * @is_relationship
  479. * Set to 1 if this term is a relationship term
  480. * @default_db
  481. * The name of the default database.
  482. *
  483. * @ingroup tripal_obo_loader
  484. */
  485. function tripal_cv_obo_process_term($term, $defaultcv, $is_relationship = 0, &$newcvs, $default_db) {
  486. // make sure we have a namespace for this term
  487. if (!array_key_exists('namespace', $term) and !($defaultcv or $defaultcv == '')) {
  488. tripal_cv_obo_quiterror("Cannot add the term: no namespace defined. " . $term['id'][0]);
  489. }
  490. // construct the term array for sending to the tripal_cv_add_cvterm function
  491. // for adding a new cvterm
  492. $t = array();
  493. $t['id'] = $term['id'][0];
  494. $t['name'] = $term['name'][0];
  495. if (array_key_exists('def', $term)) {
  496. $t['definition'] = $term['def'][0];
  497. }
  498. if (array_key_exists('subset', $term)) {
  499. $t['subset'] = $term['subset'][0];
  500. }
  501. if (array_key_exists('namespace', $term)) {
  502. $t['namespace'] = $term['namespace'][0];
  503. }
  504. if (array_key_exists('is_obsolete', $term)) {
  505. $t['is_obsolete'] = $term['is_obsolete'][0];
  506. }
  507. $t['cv_name'] = $defaultcv;
  508. $t['is_relationship'] = $is_relationship;
  509. $t['db_name'] = $default_db;
  510. // add the cvterm
  511. $cvterm = tripal_insert_cvterm($t, array('update_existing' => TRUE));
  512. if (!$cvterm) {
  513. tripal_cv_obo_quiterror("Cannot add the term " . $term['id'][0]);
  514. }
  515. if (array_key_exists('namespace', $term)) {
  516. $newcvs[$term['namespace'][0]] = $cvterm->cv_id;
  517. }
  518. // now handle other properites
  519. if (array_key_exists('is_anonymous', $term)) {
  520. //print "WARNING: unhandled tag: is_anonymous\n";
  521. }
  522. if (array_key_exists('alt_id', $term)) {
  523. foreach ($term['alt_id'] as $alt_id) {
  524. if (!tripal_cv_obo_add_cvterm_dbxref($cvterm, $alt_id)) {
  525. tripal_cv_obo_quiterror("Cannot add alternate id $alt_id");
  526. }
  527. }
  528. }
  529. if (array_key_exists('subset', $term)) {
  530. //print "WARNING: unhandled tag: subset\n";
  531. }
  532. // add synonyms for this cvterm
  533. if (array_key_exists('synonym', $term)) {
  534. if (!tripal_cv_obo_add_synonyms($term, $cvterm)) {
  535. tripal_cv_obo_quiterror("Cannot add synonyms");
  536. }
  537. }
  538. // reformat the deprecated 'exact_synonym, narrow_synonym, and broad_synonym'
  539. // types to be of the v1.2 standard
  540. if (array_key_exists('exact_synonym', $term) or array_key_exists('narrow_synonym', $term) or array_key_exists('broad_synonym', $term)) {
  541. if (array_key_exists('exact_synonym', $term)) {
  542. foreach ($term['exact_synonym'] as $synonym) {
  543. $new = preg_replace('/^\s*(\".+?\")(.*?)$/', '$1 EXACT $2', $synonym);
  544. $term['synonym'][] = $new;
  545. }
  546. }
  547. if (array_key_exists('narrow_synonym', $term)) {
  548. foreach ($term['narrow_synonym'] as $synonym) {
  549. $new = preg_replace('/^\s*(\".+?\")(.*?)$/', '$1 NARROW $2', $synonym);
  550. $term['synonym'][] = $new;
  551. }
  552. }
  553. if (array_key_exists('broad_synonym', $term)) {
  554. foreach ($term['broad_synonym'] as $synonym) {
  555. $new = preg_replace('/^\s*(\".+?\")(.*?)$/', '$1 BROAD $2', $synonym);
  556. $term['synonym'][] = $new;
  557. }
  558. }
  559. if (!tripal_cv_obo_add_synonyms($term, $cvterm)) {
  560. tripal_cv_obo_quiterror("Cannot add/update synonyms");
  561. }
  562. }
  563. // add the comment to the cvtermprop table
  564. if (array_key_exists('comment', $term)) {
  565. $comments = $term['comment'];
  566. $j = 0;
  567. foreach ($comments as $comment) {
  568. if (!tripal_cv_obo_add_cvterm_prop($cvterm, 'comment', $comment, $j)) {
  569. tripal_cv_obo_quiterror("Cannot add/update cvterm property");
  570. }
  571. $j++;
  572. }
  573. }
  574. // add any other external dbxrefs
  575. if (array_key_exists('xref', $term)) {
  576. foreach ($term['xref'] as $xref) {
  577. if (!tripal_cv_obo_add_cvterm_dbxref($cvterm, $xref)) {
  578. tripal_cv_obo_quiterror("Cannot add/update cvterm database reference (dbxref).");
  579. }
  580. }
  581. }
  582. if (array_key_exists('xref_analog', $term)) {
  583. foreach ($term['xref_analog'] as $xref) {
  584. if (!tripal_cv_obo_add_cvterm_dbxref($cvterm, $xref)) {
  585. tripal_cv_obo_quiterror("Cannot add/update cvterm database reference (dbxref).");
  586. }
  587. }
  588. }
  589. if (array_key_exists('xref_unk', $term)) {
  590. foreach ($term['xref_unk'] as $xref) {
  591. if (!tripal_cv_obo_add_cvterm_dbxref($cvterm, $xref)) {
  592. tripal_cv_obo_quiterror("Cannot add/update cvterm database reference (dbxref).");
  593. }
  594. }
  595. }
  596. // add is_a relationships for this cvterm
  597. if (array_key_exists('is_a', $term)) {
  598. foreach ($term['is_a'] as $is_a) {
  599. if (!tripal_cv_obo_add_relationship($cvterm, $defaultcv, 'is_a', $is_a, $is_relationship, $default_db)) {
  600. tripal_cv_obo_quiterror("Cannot add relationship is_a: $is_a");
  601. }
  602. }
  603. }
  604. if (array_key_exists('intersection_of', $term)) {
  605. //print "WARNING: unhandled tag: intersection_of\n";
  606. }
  607. if (array_key_exists('union_of', $term)) {
  608. //print "WARNING: unhandled tag: union_on\n";
  609. }
  610. if (array_key_exists('disjoint_from', $term)) {
  611. //print "WARNING: unhandled tag: disjoint_from\n";
  612. }
  613. if (array_key_exists('relationship', $term)) {
  614. foreach ($term['relationship'] as $value) {
  615. $rel = preg_replace('/^(.+?)\s.+?$/', '\1', $value);
  616. $object = preg_replace('/^.+?\s(.+?)$/', '\1', $value);
  617. if (!tripal_cv_obo_add_relationship($cvterm, $defaultcv, $rel, $object, $is_relationship, $default_db)) {
  618. tripal_cv_obo_quiterror("Cannot add relationship $rel: $object");
  619. }
  620. }
  621. }
  622. if (array_key_exists('replaced_by', $term)) {
  623. //print "WARNING: unhandled tag: replaced_by\n";
  624. }
  625. if (array_key_exists('consider', $term)) {
  626. //print "WARNING: unhandled tag: consider\n";
  627. }
  628. if (array_key_exists('use_term', $term)) {
  629. //print "WARNING: unhandled tag: user_term\n";
  630. }
  631. if (array_key_exists('builtin', $term)) {
  632. //print "WARNING: unhandled tag: builtin\n";
  633. }
  634. return 1;
  635. }
  636. /**
  637. * Adds a cvterm relationship
  638. *
  639. * @param $cvterm
  640. * A database object for the cvterm
  641. * @param $rel
  642. * The relationship name
  643. * @param $objname
  644. * The relationship term name
  645. * @param $defaultcv
  646. * A database object containing a record from the cv table for the
  647. * default controlled vocabulary
  648. * @object_is_relationship
  649. * Set to 1 if this term is a relationship term
  650. * @default_db
  651. * The name of the default database.
  652. *
  653. * @ingroup tripal_obo_loader
  654. */
  655. function tripal_cv_obo_add_relationship($cvterm, $defaultcv, $rel,
  656. $objname, $object_is_relationship = 0, $default_db = 'OBO_REL') {
  657. // make sure the relationship cvterm exists
  658. $term = array(
  659. 'name' => $rel,
  660. 'id' => "$default_db:$rel",
  661. 'definition' => '',
  662. 'is_obsolete' => 0,
  663. 'cv_name' => $defaultcv,
  664. 'is_relationship' => TRUE,
  665. 'db_naame' => $default_db
  666. );
  667. $relcvterm = tripal_insert_cvterm($term, array('update_existing' => FALSE));
  668. if (!$relcvterm) {
  669. // if the relationship term couldn't be found in the default_db provided
  670. // then do on more check to find it in the relationship ontology
  671. $term = array(
  672. 'name' => $rel,
  673. 'id' => "OBO_REL:$rel",
  674. 'definition' => '',
  675. 'is_obsolete' => 0,
  676. 'cv_name' => $defaultcv,
  677. 'is_relationship' => TRUE,
  678. 'db_name' => 'OBO_REL'
  679. );
  680. $relcvterm = tripal_insert_cvterm($term, array('update_existing' => FALSE));
  681. if (!$relcvterm) {
  682. tripal_cv_obo_quiterror("Cannot find the relationship term in the current ontology or in the relationship ontology: $rel\n");
  683. }
  684. }
  685. // get the object term
  686. $oterm = tripal_cv_obo_get_term($objname);
  687. if (!$oterm) {
  688. tripal_cv_obo_quiterror("Could not find object term $objname\n");
  689. }
  690. $objterm = array();
  691. $objterm['id'] = $oterm['id'][0];
  692. $objterm['name'] = $oterm['name'][0];
  693. if (array_key_exists('def', $oterm)) {
  694. $objterm['definition'] = $oterm['def'][0];
  695. }
  696. if (array_key_exists('subset', $oterm)) {
  697. $objterm['subset'] = $oterm['subset'][0];
  698. }
  699. if (array_key_exists('namespace', $oterm)) {
  700. $objterm['namespace'] = $oterm['namespace'][0];
  701. }
  702. if (array_key_exists('is_obsolete', $oterm)) {
  703. $objterm['is_obsolete'] = $oterm['is_obsolete'][0];
  704. }
  705. $objterm['cv_name' ] = $defaultcv;
  706. $objterm['is_relationship'] = $object_is_relationship;
  707. $objterm['db_name'] = $default_db;
  708. $objcvterm = tripal_insert_cvterm($objterm, array('update_existing' => TRUE));
  709. if (!$objcvterm) {
  710. tripal_cv_obo_quiterror("Cannot add cvterm " . $oterm['name'][0]);
  711. }
  712. // check to see if the cvterm_relationship already exists, if not add it
  713. $values = array(
  714. 'type_id' => $relcvterm->cvterm_id,
  715. 'subject_id' => $cvterm->cvterm_id,
  716. 'object_id' => $objcvterm->cvterm_id
  717. );
  718. $options = array('statement_name' => 'sel_cvtermrelationship_tysuob');
  719. $result = chado_select_record('cvterm_relationship', array('*'), $values, $options);
  720. if (count($result) == 0) {
  721. $options = array(
  722. 'statement_name' => 'ins_cvtermrelationship_tysuob',
  723. 'return_record' => FALSE
  724. );
  725. $success = chado_insert_record('cvterm_relationship', $values, $options);
  726. if (!$success) {
  727. tripal_cv_obo_quiterror("Cannot add term relationship: '$cvterm->name' $rel '$objcvterm->name'");
  728. }
  729. }
  730. return TRUE;
  731. }
  732. /**
  733. * Retreives the term array from the temp loading table for a given term id.
  734. *
  735. * @param id
  736. * The id of the term to retrieve
  737. *
  738. * @ingroup tripal_obo_loader
  739. */
  740. function tripal_cv_obo_get_term($id) {
  741. $values = array('id' => $id);
  742. $options = array('statement_name' => 'sel_tripalobotemp_id');
  743. $result = chado_select_record('tripal_obo_temp', array('stanza'), $values, $options);
  744. if (count($result) == 0) {
  745. return FALSE;
  746. }
  747. return unserialize(base64_decode($result[0]->stanza));
  748. }
  749. /**
  750. * Adds the synonyms to a term
  751. *
  752. * @param term
  753. * An array representing the cvterm. It must have a 'synonym' key/value pair.
  754. * @param cvterm
  755. * The database object of the cvterm to which the synonym will be added.
  756. *
  757. * @ingroup tripal_obo_loader
  758. */
  759. function tripal_cv_obo_add_synonyms($term, $cvterm) {
  760. // make sure we have a 'synonym_type' vocabulary
  761. $syncv = tripal_insert_cv('synonym_type', 'A vocabulary added by the Tripal CV module OBO loader for storing synonym types.');
  762. // now add the synonyms
  763. if (array_key_exists('synonym', $term)) {
  764. foreach ($term['synonym'] as $synonym) {
  765. // separate out the synonym definition and the synonym type
  766. $def = preg_replace('/^\s*"(.*)"\s*.*$/', '\1', $synonym);
  767. // the scope will be 'EXACT', etc...
  768. $scope = drupal_strtolower(preg_replace('/^.*"\s+(.*?)\s+.*$/', '\1', $synonym));
  769. if (!$scope) { // if no scope then default to 'exact'
  770. $scope = 'exact';
  771. }
  772. // make sure the synonym type exists in the 'synonym_type' vocabulary
  773. $values = array(
  774. 'name' => $scope,
  775. 'cv_id' => array(
  776. 'name' => 'synonym_type',
  777. ),
  778. );
  779. $options = array('statement_name' => 'sel_cvterm_nacv', 'is_updlicate' => 1);
  780. $results = chado_select_record('cvterm', array('*'), $values, $options);
  781. // if it doesn't exist then add it
  782. if (!$results) {
  783. // build a 'term' object so we can add the missing term
  784. $term = array(
  785. 'name' => $scope,
  786. 'id' => "internal:$scope",
  787. 'definition' => '',
  788. 'is_obsolete' => 0,
  789. 'cv_name' => $syncv->name,
  790. 'is_relationship' => FALSE
  791. );
  792. $syntype = tripal_insert_cvterm($term, array('update_existing' => TRUE));
  793. if (!$syntype) {
  794. tripal_cv_obo_quiterror("Cannot add synonym type: internal:$scope");
  795. }
  796. }
  797. else {
  798. $syntype = $results[0];
  799. }
  800. // make sure the synonym doesn't already exists
  801. $values = array(
  802. 'cvterm_id' => $cvterm->cvterm_id,
  803. 'synonym' => $def
  804. );
  805. $options = array('statement_name' => 'sel_cvtermsynonym_cvsy');
  806. $results = chado_select_record('cvtermsynonym', array('*'), $values, $options);
  807. if (count($results) == 0) {
  808. $values = array(
  809. 'cvterm_id' => $cvterm->cvterm_id,
  810. 'synonym' => $def,
  811. 'type_id' => $syntype->cvterm_id
  812. );
  813. $options = array(
  814. 'statement_name' => 'ins_cvtermsynonym_cvsy',
  815. 'return_record' => FALSE
  816. );
  817. $success = chado_insert_record('cvtermsynonym', $values, $options);
  818. if (!$success) {
  819. tripal_cv_obo_quiterror("Failed to insert the synonym for term: $name ($def)");
  820. }
  821. }
  822. // now add the dbxrefs for the synonym if we have a comma in the middle
  823. // of a description then this will cause problems when splitting os lets
  824. // just change it so it won't mess up our splitting and then set it back
  825. // later.
  826. /**
  827. $synonym = preg_replace('/(".*?),\s(.*?")/','$1,_$2',$synonym);
  828. $dbxrefs = preg_split("/, /",preg_replace('/^.*\[(.*?)\]$/','\1',$synonym));
  829. foreach ($dbxrefs as $dbxref) {
  830. $dbxref = preg_replace('/,_/',", ",$dbxref);
  831. if ($dbxref) {
  832. tripal_cv_obo_add_cvterm_dbxref($syn,$dbxref);
  833. }
  834. }
  835. */
  836. }
  837. }
  838. return TRUE;
  839. }
  840. /**
  841. * Parse the OBO file and populate the templ loading table
  842. *
  843. * @param $file
  844. * The path on the file system where the ontology can be found
  845. * @param $header
  846. * An array passed by reference that will be populated with the header
  847. * information from the OBO file
  848. * @param $jobid
  849. * The job_id of the job from the Tripal jobs management system.
  850. *
  851. * @ingroup tripal_obo_loader
  852. */
  853. function tripal_cv_obo_parse($obo_file, &$header, $jobid) {
  854. $in_header = 1;
  855. $stanza = array();
  856. $default_db = '_global';
  857. $line_num = 0;
  858. $num_read = 0;
  859. $intv_read = 0;
  860. $filesize = filesize($obo_file);
  861. $interval = intval($filesize * 0.01);
  862. if ($interval < 1) {
  863. $interval = 1;
  864. }
  865. // iterate through the lines in the OBO file and parse the stanzas
  866. $fh = fopen($obo_file, 'r');
  867. while ($line = fgets($fh)) {
  868. $line_num++;
  869. $size = drupal_strlen($line);
  870. $num_read += $size;
  871. $intv_read += $size;
  872. $line = trim($line);
  873. // update the job status every 1% features
  874. if ($jobid and $intv_read >= $interval) {
  875. $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
  876. print "Parsing Line $line_num (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
  877. tripal_set_job_progress($jobid, intval(($num_read / $filesize) * 33.33333333));
  878. $intv_read = 0;
  879. }
  880. // remove newlines
  881. $line = rtrim($line);
  882. // remove any special characters that may be hiding
  883. $line = preg_replace('/[^(\x20-\x7F)]*/', '', $line);
  884. // skip empty lines
  885. if (strcmp($line, '') == 0) {
  886. continue;
  887. }
  888. //remove comments from end of lines
  889. $line = preg_replace('/^(.*?)\!.*$/', '\1', $line); // TODO: if the explamation is escaped
  890. // at the first stanza we're out of header
  891. if (preg_match('/^\s*\[/', $line)) {
  892. $in_header = 0;
  893. // store the stanza we just finished reading
  894. if (sizeof($stanza) > 0) {
  895. // add the term to the temp table
  896. $values = array(
  897. 'id' => $stanza['id'][0],
  898. 'stanza' => base64_encode(serialize($stanza)),
  899. 'type' => $type,
  900. );
  901. $options = array('statement_name' => 'ins_tripalobotemp_all');
  902. $success = chado_insert_record('tripal_obo_temp', $values, $options);
  903. if (!$success) {
  904. tripal_report_error('T_obo_loader', "ERROR: Cannot insert stanza into temporary table.", array(), 'error');
  905. exit;
  906. }
  907. }
  908. // get the stanza type: Term, Typedef or Instance
  909. $type = preg_replace('/^\s*\[\s*(.+?)\s*\]\s*$/', '\1', $line);
  910. // start fresh with a new array
  911. $stanza = array();
  912. continue;
  913. }
  914. // break apart the line into the tag and value but ignore any escaped colons
  915. preg_replace("/\\:/", "|-|-|", $line); // temporarily replace escaped colons
  916. $pair = explode(":", $line, 2);
  917. $tag = $pair[0];
  918. $value = ltrim(rtrim($pair[1]));// remove surrounding spaces
  919. // if this is the ID then look for the default DB
  920. $matches = array();
  921. if ($tag == 'id' and preg_match('/^(.+?):.*$/', $value, $matches)) {
  922. $default_db = $matches[1];
  923. }
  924. $tag = preg_replace("/\|-\|-\|/", "\:", $tag); // return the escaped colon
  925. $value = preg_replace("/\|-\|-\|/", "\:", $value);
  926. if ($in_header) {
  927. if (!array_key_exists($tag, $header)) {
  928. $header[$tag] = array();
  929. }
  930. $header[$tag][] = $value;
  931. }
  932. else {
  933. if (!array_key_exists($tag, $stanza)) {
  934. $stanza[$tag] = array();
  935. }
  936. $stanza[$tag][] = $value;
  937. }
  938. }
  939. // now add the last term in the file
  940. if (sizeof($stanza) > 0) {
  941. $values = array(
  942. 'id' => $stanza['id'][0],
  943. 'stanza' => base64_encode(serialize($stanza)),
  944. 'type' => $type,
  945. );
  946. $options = array('statement_name' => 'ins_tripalobotemp_all');
  947. chado_insert_record('tripal_obo_temp', $values, $options);
  948. if (!$success) {
  949. tripal_report_error('T_obo_loader', "ERROR: Cannot insert stanza into temporary table.", array(), 'error');
  950. exit;
  951. }
  952. $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
  953. print "Parsing Line $line_num (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
  954. tripal_set_job_progress($jobid, intval(($num_read / $filesize) * 33.33333333));
  955. }
  956. return $default_db;
  957. }
  958. /**
  959. * Adds a database reference to a cvterm
  960. *
  961. * @param cvterm
  962. * The database object of the cvterm to which the synonym will be added.
  963. * @param xref
  964. * The cross refernce. It should be of the form from the OBO specification
  965. *
  966. * @ingroup tripal_obo_loader
  967. */
  968. function tripal_cv_obo_add_cvterm_dbxref($cvterm, $xref) {
  969. $dbname = preg_replace('/^(.+?):.*$/', '$1', $xref);
  970. $accession = preg_replace('/^.+?:\s*(.*?)(\{.+$|\[.+$|\s.+$|\".+$|$)/', '$1', $xref);
  971. $description = preg_replace('/^.+?\"(.+?)\".*?$/', '$1', $xref);
  972. $dbxrefs = preg_replace('/^.+?\[(.+?)\].*?$/', '$1', $xref);
  973. if (!$accession) {
  974. tripal_cv_obo_quiterror();
  975. tripal_report_error("T_obo_loader", TRIPAL_WARNING, "Cannot add a dbxref without an accession: '$xref'", NULL);
  976. return FALSE;
  977. }
  978. // if the xref is a database link, handle that specially
  979. if (strcmp($dbname, 'http') == 0) {
  980. $accession = $xref;
  981. $dbname = 'URL';
  982. }
  983. // add the database
  984. $db = tripal_insert_db(array('name' => $dbname));
  985. if (!$db) {
  986. tripal_cv_obo_quiterror("Cannot find database '$dbname' in Chado.");
  987. }
  988. // now add the dbxref
  989. $dbxref = tripal_cv_obo_add_dbxref($db->db_id, $accession, '', $description);
  990. if (!$dbxref) {
  991. tripal_cv_obo_quiterror("Cannot find or add the database reference (dbxref)");
  992. }
  993. // finally add the cvterm_dbxref but first check to make sure it exists
  994. $values = array(
  995. 'cvterm_id' => $cvterm->cvterm_id,
  996. 'dbxref_id' => $dbxref->dbxref_id,
  997. );
  998. $options = array('statement_name' => 'sel_cvtermdbxref_cvdb');
  999. $result = chado_select_record('cvterm_dbxref', array('*'), $values, $options);
  1000. if (count($result) == 0) {
  1001. $ins_options = array(
  1002. 'statement_name' => 'ins_cvtermdbxref_cvdb',
  1003. 'return_record' => FALSE
  1004. );
  1005. $result = chado_insert_record('cvterm_dbxref', $values, $ins_options);
  1006. if (!$result) {
  1007. tripal_cv_obo_quiterror("Cannot add cvterm_dbxref: $xref");
  1008. return FALSE;
  1009. }
  1010. }
  1011. return TRUE;
  1012. }
  1013. /**
  1014. * Adds a property to a cvterm
  1015. *
  1016. * @param cvterm
  1017. * A database object for the cvterm to which properties will be added
  1018. * @param $property
  1019. * The name of the property to add
  1020. * @param $value
  1021. * The value of the property
  1022. * @param rank
  1023. * The rank of the property
  1024. *
  1025. * @ingroup tripal_obo_loader
  1026. */
  1027. function tripal_cv_obo_add_cvterm_prop($cvterm, $property, $value, $rank) {
  1028. // make sure the 'cvterm_property_type' CV exists
  1029. $cv = tripal_insert_cv('cvterm_property_type', '');
  1030. if (!$cv) {
  1031. tripal_cv_obo_quiterror("Cannot add/find cvterm_property_type cvterm");
  1032. }
  1033. // get the property type cvterm. If it doesn't exist then we want to add it
  1034. $values = array(
  1035. 'name' => $property,
  1036. 'cv_id' => $cv->cv_id,
  1037. );
  1038. $options = array('statement_name' => 'sel_cvterm_nacv_na');
  1039. $results = chado_select_record('cvterm', array('*'), $values, $options);
  1040. if (count($results) == 0) {
  1041. $term = array(
  1042. 'name' => $property,
  1043. 'id' => "internal:$property",
  1044. 'definition' => '',
  1045. 'is_obsolete' => 0,
  1046. 'cv_name' => $cv->name,
  1047. 'is_relationship' => FALSE,
  1048. );
  1049. $cvproptype = tripal_insert_cvterm($term, array('update_existing' => FALSE));
  1050. if (!$cvproptype) {
  1051. tripal_cv_obo_quiterror("Cannot add cvterm property: internal:$property");
  1052. return FALSE;
  1053. }
  1054. }
  1055. else {
  1056. $cvproptype = $results[0];
  1057. }
  1058. // remove any properties that currently exist for this term. We'll reset them
  1059. if ($rank == 0) {
  1060. $values = array('cvterm_id' => $cvterm->cvterm_id);
  1061. $options = array('statement_name' => 'del_cvtermprop_cv');
  1062. $success = chado_delete_record('cvtermprop', $values, $options);
  1063. if (!$success) {
  1064. tripal_cv_obo_quiterror("Could not remove existing properties to update property $property for term\n");
  1065. return FALSE;
  1066. }
  1067. }
  1068. // now add the property
  1069. $values = array(
  1070. 'cvterm_id' => $cvterm->cvterm_id,
  1071. 'type_id' => $cvproptype->cvterm_id,
  1072. 'value' => $value,
  1073. 'rank' => $rank,
  1074. );
  1075. $options = array(
  1076. 'statement_name' => 'ins_cvtermprop_cvtyvara',
  1077. 'return_record' => FALSE,
  1078. );
  1079. $result = chado_insert_record('cvtermprop', $values, $options);
  1080. if (!$result) {
  1081. tripal_cv_obo_quiterror("Could not add property $property for term\n");
  1082. return FALSE;
  1083. }
  1084. return TRUE;
  1085. }
  1086. /**
  1087. * Adds a database cross reference to a cvterm
  1088. *
  1089. * @param db_id
  1090. * The database ID of the cross reference
  1091. * @param accession
  1092. * The cross reference's accession
  1093. * @param $version
  1094. * The version of the dbxref
  1095. * @param $description
  1096. * The description of the cross reference
  1097. *
  1098. * @ingroup tripal_obo_loader
  1099. */
  1100. function tripal_cv_obo_add_dbxref($db_id, $accession, $version='', $description='') {
  1101. // check to see if the dbxref exists if not, add it
  1102. $values = array(
  1103. 'db_id' => $db_id,
  1104. 'accession' => $accession,
  1105. );
  1106. $options = array('statement_name' => 'sel_dbxref_idac');
  1107. $result = chado_select_record('dbxref', array('dbxref_id'), $values, $options);
  1108. if (count($result) == 0) {
  1109. $ins_values = array(
  1110. 'db_id' => $db_id,
  1111. 'accession' => $accession,
  1112. 'version' => $version,
  1113. 'description' => $description,
  1114. );
  1115. $ins_options = array(
  1116. 'statement_name' => 'ins_dbxref_idacvede',
  1117. 'return_record' => FALSE
  1118. );
  1119. $result = chado_insert_record('dbxref', $ins_values, $ins_options);
  1120. if (!$result) {
  1121. tripal_cv_obo_quiterror("Failed to insert the dbxref record $accession");
  1122. return FALSE;
  1123. }
  1124. $result = chado_select_record('dbxref', array('dbxref_id'), $values, $options);
  1125. }
  1126. return $result[0];
  1127. }