BioPHP - Sequence Database Class (original)
Original code submitted by josebaCode bellow is covered by GNU GPL v2 license.
Description
Last change: 2005/12/29 14:38 | Recent Changes(short for \"Sequence Database\") Contains code for the SeqDB Class.
Code
Last change: 2005/12/29 14:38 | Download original | Recent Changes | Original code<?php require_once(\"etc.inc\"); require_once(\"seq.inc\"); // ================== FUNCTIONS ======================== /* We begin by describing parse_swissprot() first. parse_swissprot() parses the Feature Table lines (those that begin with FT) in a Swissprot data file, extracts the feature key name, from endpoint, to endpoint, and description, and stores them in a (simple) array. process_ft() then pushes this array into a larger associative array, called $swiss, which is also an attribute of the Seq object. It is assigned a key of the form: FT_<feature_key_name>. Examples are: FT_PEPTIDE, FT_DISULFID. */ function process_ft(&$swiss, $ft_r) { foreach($ft_r as $element) { $index = \"FT_\" . $element[0]; array_shift($element); if (count($swiss[$index]) == 0) { $swiss[$index] = array(); array_push($swiss[$index], $element); } else array_push($swiss[$index], $element); } } // at_entrystart() tests if the file pointer is at the start of a new sequence entry. function at_entrystart($linestr, $dbformat) { if ($dbformat == \"GENBANK\") return (substr($linestr,0,5) == \"LOCUS\"); elseif ($dbformat == \"SWISSPROT\") return (substr($linestr,0,2) == \"ID\"); } // get_entryid() gets the primary accession number of the sequence entry which we are // currently processing. This uniquely identifies a sequence entry. function get_entryid(&$flines, $linestr, $dbformat) { if ($dbformat == \"GENBANK\") return trim(substr($linestr, 12, 16)); elseif ($dbformat == \"SWISSPROT\") { list($lineno, $linestr) = each($flines); if (substr($linestr,0,2) == \"AC\") { $words = preg_split(\"/;/\", intrim(substr($linestr,5))); prev($flines); return $words[0]; } } } // line2r() copies the lines belonging to a single sequence entry into an array. function line2r($fpseq) { $flines = array(); while(1) { $linestr = fgets($fpseq, 101); $flines[] = $linestr; if (left($linestr,2) == \'//\') return $flines; } return FALSE; } // isa_qualifier() tests if the file pointer is at a line containing a feature qualifier. // This applies only to GenBank sequence files. function isa_qualifier($str) { if (firstchar($str) == \'/\') return true; else return false; } // fseekline() gets the byte offset (from beginning of file) of a particular line. The file is // identified by $fp file pointer, while the line is identified by $lineno, which is zero-based. function fseekline($fp, $lineno) { $linectr = 0; fseek($fp, 0); while(!feof($fp)) { $linestr = fgets($fp,101); if ($linectr == $lineno) { fseek($fp, $byteoff); return $byteoff; } $linectr++; $byteoff = ftell($fp); } } // bsrch_tabfile() searches for a particular sequence id ($seqid) within an *.IDX file // (identified by $fp file pointer), and returns data located in its $col-th column. function bsrch_tabfile($fp, $col, $seqid) { $linectr = 0; fseek($fp, 0); while(!feof($fp)) { fgets($fp, 41); $linectr++; } $lastline = $linectr; rewind($fp); if ($fp == FALSE) die(\"CANT OPEN FILE\"); $searchspace = $lastline; $floor = 0; $ceiling = $lastline - 1; while(1) { $offset = ((int) ($searchspace/2)); $lineno = $floor + $offset; fseekline($fp, $lineno); $word = preg_split(\"/\\s+/\", trim(fgets($fp,81))); if ($word[$col] == $seqid) { $word[] = $lineno; return $word; } elseif ($seqid > $word[$col]) { $floor = $lineno + 1; $searchspace = $ceiling - $floor + 1; if ($searchspace <= 0) return FALSE; } else { $ceiling = $lineno - 1; $searchspace = $ceiling - $floor + 1; if ($searchspace <= 0) return FALSE; } } // fclose($fpidx); } // ================== CLASSES ======================== class SeqDB { // OPENS definition of SEQDB CLASS. var $dbname; var $data_fn; var $data_fp; var $dir_fn; var $dir_fp; var $seqptr; var $seqcount; var $dbformat; var $bof; var $eof; // We need the functions bof() and eof() to determine if we\'ve reached the end of // file or not. // Two ways of doing this: 1) examine value of seqptr, or 2) maintain boolean variables eof and bof // first() positions the sequence pointer (i.e. the seqptr property of a Seq object) to // the first sequence in a database (SeqDB object). function first() { $this->seqptr = 0; } // last() positions the sequence pointer (i.e. the seqptr property of a Seq object) to // the last sequence in a database (SeqDB object). function last() { $this->seqptr = $this->seqcount-1; } // prev() (short for previous) positions the sequence pointer (i.e. the seqptr property of // a Seq object) to the sequence that comes before the current sequence. function prev() { if ($this->seqptr > 0) $this->seqptr--; else $this->bof = TRUE; } // next() positions the sequence pointer (i.e. the seqptr property of a Seq object) to the // sequence that comes after the current sequence. function next() { if ($this->seqptr < $this->seqcount-1) $this->seqptr++; else $this->eof = TRUE; } // fetch() retrieves all data from the specified sequence record and returns them in the // form of a Seq object. This method invokes one of several parser methods. function fetch() { if ($this->data_fn == \"\") die(\"Cannot invoke fetch() method from a closed object.\"); @$seqid = func_get_arg(0); // IDX and DIR files remain open for the duration of the FETCH() method. $fp = fopen($this->data_fn, \"r\"); $fpdir = fopen($this->dir_fn, \"r\"); if ($seqid != FALSE) { $idx_r = bsrch_tabfile($fp, 0, $seqid); if ($idx_r == FALSE) return FALSE; else $this->seqptr = $idx_r[3]; } else { // For now, SEQPTR determines CURRENT SEQUENCE ID. Alternative is to track curr line. fseekline($fp, $this->seqptr); $idx_r = preg_split(\"/\\s+/\", trim(fgets($fp, 81))); } $dir_r = bsrch_tabfile($fpdir, 0, $idx_r[1]); $fpseq = fopen($dir_r[1], \"r\"); fseekline($fpseq, $idx_r[2]); $flines = line2r($fpseq); $myseq = new seq(); if ($this->dbformat == \"GENBANK\") $myseq = $this->parse_id($flines); elseif ($this->dbformat == \"SWISSPROT\") $myseq = $this->parse_swissprot($flines); fclose($fp); fclose($fpdir); fclose($fpseq); return $myseq; } // parse_swissprot() parses a Swissprot data file and returns a Seq object containing parsed data. function parse_swissprot($flines) { // OPENS parse_swissprot() function $accession = array(); $date_r = array(); $desc = \"\"; $desc_lnctr = 0; $gename_r = array(); $os_r = array(); $os_linectr = 0; $os_str = \"\"; $oc_linectr = 0; $oc_str = \"\"; $ref_r = array(); $ra_r = array(); $ra_ctr = 0; $ra_str = \"\"; $rl_ctr = 0; $rl_str = \"\"; $db_r = array(); $ft_r = array(); $kw_str = \"\"; $kw_r = array(); while ( list($no, $linestr) = each($flines) ) { // OPENS 1st (outermost) while ( list($no, $linestr) = each($flines) ) $linelabel = left($linestr, 2); $linedata = trim(substr($linestr, 5)); $lineend = right($linedata, 1); if (left($linestr, 2) == \"ID\") { // OPENS if (left($linestr, 2) == \"ID\") $words = preg_split(\"/;/\", substr($linestr, 5)); $endc = preg_split(\"/\\s/\", $words[0]); $entry_name = $endc[0]; $namesrc = preg_split(\"/_/\", $entry_name); $protein_name = $namesrc[0]; $protein_source = $namesrc[1]; $data_class = $endc[1]; $moltype = $words[1]; $length = (int) substr($words[2], 0, strlen($words[2])-4); } // CLOSES if (left($linestr, 2) == \"ID\") if (left($linestr, 2) == \"AC\") { // OPENS if (left($linestr, 2) == \"AC\") $accstr = $linedata; $accstr = substr($accstr, 0, strlen($accstr)-1); $accline = preg_split(\"/;/\", intrim($accstr)); $accession = array_merge($accession, $accline); } // CLOSES if (left($linestr, 2) == \"AC\") if (left($linestr, 2) == \"DT\") { // OPENS if (left($linestr, 2) == \"DT\") // DT DD-MMM-YEAR (REL. XX, COMMENT) $datestr = $linedata; $datestr = substr($datestr, 0, strlen($datestr)-1); $words = preg_split(\"/\\(/\", $datestr); // ( \"DD-MMM-YEAR \", \"REL. XX, COMMENT\") $firstcomma = strpos($words[1], \",\"); $comment = trim(substr($words[1], $firstcomma+1)); // ( \"CREATED\" => (date, rel), \"LAST SEQUENCE UPDATE\" => (date, rel), // \"LAST ANNOTATION UPDATE\" => (date, rel), COMMENT1 => (date, rel), // \"COMMENT2\" => (date, rel), ... ) if ($comment == \"CREATED\") { // OPENS if ($comment == \"CREATED\") // this DT line is a DATE CREATED line. $create_date = substr($words[0], 0, 11); $create_rel = substr($words[1], 5, ($firstcomma-5)); $date_r[$comment] = array($create_date, $create_rel); } // CLOSES if ($comment == \"CREATED\") elseif ($comment == \"LAST SEQUENCE UPDATE\") { // OPENS elseif ($comment == \"LAST SEQUENCE UPDATE\") $sequpd_date = substr($words[0], 0, 11); $sequpd_rel = substr($words[1], 5, ($firstcomma-5)); $date_r[$comment] = array($sequpd_date, $sequpd_rel); } // CLOSES elseif ($comment == \"LAST SEQUENCE UPDATE\") elseif ($comment == \"LAST ANNOTATION UPDATE\") { // OPENS elseif ($comment == \"LAST ANNOTATION UPDATE\") $notupd_date = substr($words[0], 0, 11); $notupd_rel = substr($words[1], 5, ($firstcomma-5)); $date_r[$comment] = array($notupd_date, $notupd_rel); } // CLOSES elseif ($comment == \"LAST ANNOTATION UPDATE\") else { // OPENS else part of if ($comment == \"CREATED\") // For now, we do not check vs. duplicate comments. // We just overwrite the older comment with new one. $other_comment = $comment; $other_date = substr($words[0], 0, 11); $other_rel = substr($words[1], 5, ($firstcomma-5)); $date_r[$comment] = array($other_date, $other_rel); } // CLOSES else part of if ($comment == \"CREATED\") } // CLOSES if (left($linestr, 2) == \"DT\") if (left($linestr, 2) == \"DE\") { // OPENS if (left($linestr, 2) == \"DE\") $desc_lnctr++; $linestr = $linedata; if ($desc_lnctr == 1) $desc .= $linestr; else $desc .= \" \" . $linestr; // Checks if (FRAGMENT) or (FRAGMENTS) is found at the end // of the DE line to determine if sequence is complete. if (right($linestr, 1) == \".\") { // OPENS if (right($linestr, 1) == \".\") if ( (strtoupper(right($linestr, 11)) == \"(FRAGMENT).\") or (strtoupper(right($linestr, 12)) == \"(FRAGMENTS).\") ) $is_fragment = TRUE; else $is_fragment = FALSE; } // CLOSE if (right($linestr, 1) == \".\") } // CLOSES if (left($linestr, 2) == \"DE\") if ($linelabel == \"KW\") { $kw_str .= $linedata; if ($lineend == \".\") { $kw_str = rem_right($kw_str); $kw_r = preg_split(\"/;/\", $kw_str); array_walk($kw_r, \"trim_element\"); $kw_str = \"\"; } } if ($linelabel == \"OS\") { // OPENS if ($linelabel == \"OS\") $os_linectr++; if ($lineend != \".\") { // we are not yet at the last OS line. if ($os_linectr == 1) $os_str .= $linedata; else $os_str .= \" $linedata\"; } else { // we are at the last OS line. $os_str .= \" $linedata\"; $os_str = rem_right($os_str); $os_line = preg_split(\"/\\, AND /\", $os_str); } } // CLOSES if ($linelabel == \"OS\") if ($linelabel == \"OG\") $organelle = rem_right($linedata); if ($linelabel == \"OC\") { $oc_linectr++; if ($lineend != \".\") { // we are not yet at the last OS line. if ($oc_linectr == 1) $oc_str .= $linedata; else $oc_str .= \" $linedata\"; } else { // we are at the last OS line. $oc_str .= \" $linedata\"; $oc_str = rem_right($oc_str); $oc_line = preg_split(\"/;/\", $oc_str); array_walk($oc_line, \"trim_element\"); } } if ($linelabel == \"FT\") { $ft_key = trim(substr($linestr, 5, 8)); $ft_from = (int) trim(substr($linestr, 14, 6)); $ft_to = (int) trim(substr($linestr, 21, 6)); $ft_desc = rem_right(trim(substr($linestr, 34))); $ft_r[] = array($ft_key, $ft_from, $ft_to, $ft_desc); } // ( rn => ( \"rp\" => \"my rp\", \"rc\" => (\"tok1\" => \"value\", ...) ) ) // ( 10 => ( \"RP\" => \"my rp\", \"RC\" => (\"PLASMID\" => \"PLA_VAL\", ... ) ) ) // Example: DR AARHUS/GHENT-2DPAGE; 8006; IEF. if ($linelabel == \"DR\") { // DR DATA_BANK_IDENTIFIER; PRIMARY_IDENTIFIER; SECONDARY_IDENTIFIER // We assume that all three data items are mandatory/present in all DR entries. // ( refno => ( (dbname1, pid1, sid1), (dbname2, pid2, sid2), ... ), 1 => ( ... ) ) // ( 0 => ( (REBASE, pid1, sid1), (WORPEP, pid2, sid2), ... ), 1 => ( ... ) ) $linedata = rem_right($linedata); $dr_line = preg_split(\"/;/\", $linedata); array_walk($dr_line, \"trim_element\"); $db_name = $dr_line[0]; $db_pid = $dr_line[1]; $db_sid = $dr_line[2]; $db_r[] = array($db_name, $db_pid, $db_sid); } if ($linelabel == \"RN\") { // OPENS \"RN\" // Remove the [ and ] between the reference number. $refno = substr(rem_right($linedata), 1); $rc_ctr = 0; $rc_str = \"\"; $rc_flag = FALSE; $inner_r = array(); while ( list($no, $linestr) = each($flines) ) { // OPENS 2nd WHILE $linelabel = left($linestr, 2); $linedata = trim(substr($linestr, 5)); $lineend = right($linedata, 1); if ($linelabel == \"RP\") $inner_r[\"RP\"] = $linedata; elseif ($linelabel == \"RC\") { // OPENS elseif ($linelabel == \"RC\") $rc_str .= $linedata; while ( list($no, $linestr) = each($flines) ) { // OPENS 3rd WHILE $linelabel = left($linestr, 2); $linedata = trim(substr($linestr, 5)); $lineend = right($linedata, 1); if ($linelabel == \"RC\") $rc_str .= \" $linedata\"; else { // opens else prev($flines); break; } // closes else } // CLOSES 3rd WHILE // we remove the last character if it is \";\" $rc_str = trim($rc_str); if (right($rc_str,1) == \";\") $rc_str = rem_right($rc_str); $rc_line = preg_split(\"/;/\", trim($rc_str)); array_walk($rc_line, \"trim_element\"); $innermost = array(); foreach($rc_line as $tokval_str) { // here we assume that there is no whitespace // before or after (left or right of) the \"=\". $tokval_r = preg_split(\"/=/\", $tokval_str); $token = $tokval_r[0]; $value = $tokval_r[1]; $innermost[$token] = $value; } $inner_r[\"RC\"] = $innermost; } // CLOSES elseif ($linelabel == \"RC\") elseif ($linelabel == \"RM\") { // We have no idea what RM is about, so we assume it\'s a single-line entry. // which may occur 0 to 1 times inside a SWISSPROT SEQUENCE RECORD. $inner_r[\"RM\"] = $linedata; } elseif ($linelabel == \"RX\") { $linedata = rem_right($linedata); $rx_line = preg_split(\"/;/\", intrim($linedata)); $inner_r[\"RX_BDN\"] = $rx_line[0]; $inner_r[\"RX_ID\"] = $rx_line[1]; } elseif ($linelabel == \"RA\") { $ra_ctr++; if ($ra_ctr == 1) $ra_str = $linedata; else $ra_str .= \" $linedata\"; if ($lineend == \";\") { $ra_str = rem_right($ra_str); $ra_r = preg_split(\"/\\,/\", $ra_str); array_walk($ra_r, \"trim_element\"); $inner_r[\"RA\"] = $ra_r; } } elseif ($linelabel == \"RL\") { $rl_ctr++; if ($rl_ctr == 1) $rl_str = $linedata; else $rl_str .= \" $linedata\"; } else { $inner_r[\"RL\"] = $rl_str; prev($flines); break; } } // CLOSES 2nd WHILE $ref_r[$refno-1] = $inner_r; $ra_str = \"\"; $ra_ctr = 0; $rl_str = \"\"; $rl_ctr = 0; } // CLOSES \"RN\" if (left($linestr, 2) == \"GN\") { // OPENS if (left($linestr, 2) == \"GN\") // GN is always exactly one line. // GNAME1 OR GNAME2 ( (GNAME1, GNAME2) ) // GNAME1 AND GNAME2 ( (GNAME1), (GNAME2) ) // GNAME1 AND (GNAME2 OR GNAME3) ( (GNAME1), (GNAME2, GNAME3) ) // GNAME1 OR (GNAME2 AND GNAME3) NOT POSSIBLE!!! /* ALGORITHM: 1) Split expressions by \" AND \". 2) Test each \"token\" if in between parentheses or not. 3) If not, then token is a singleton, else it\'s a multiple-ton. 4) Singletons are translated into (GNAME1). Multiple-tons are translated into (GNAME1, GNAME 2). 5) Push gene name array into larger array. Go to next token. */ // Remove \"GN \" at the beginning of our line. $linestr = trim(substr($linestr, 5)); // Remove the last character which is always a period. $linestr = substr($linestr, 0, strlen($linestr)-1); // Go here if you detect at least one ( or ). if ( is_false(strpos($linestr, \"(\")) ) { // GN Line does not contain any parentheses. // Ergo, it is made up of all OR\'s or AND\'s but not both. if (strpos($linestr, \" OR \") != FALSE) { // Case 1: GNAME1 OR GNAME2. $temp = preg_split(\"/ OR /\", $linestr); $gename_r[] = $temp; } elseif (strpos($linestr, \" AND \") != FALSE) { // Case 2: GNAME1 AND GNAME2 AND GNAME3. $temp = preg_split(\"/ AND /\", $linestr); foreach($temp as $gene) $gename_r[] = array($gene); } else $gename_r[] = array($linestr); // Case 0: GN GENENAME1. One gene name (no OR, AND). } else { // OPENS else part of if ( is_false(strpos($linestr, \"(\")) ) // GN Line contains at least one pair of parentheses. // Case 3: GNAME1 AND (GNAME2 OR GNAME3) => ( (GNAME1), (GNAME2, GNAME3) ) // COMMENTS # 1 below. $temp = preg_split(\"/ AND /\", $linestr); foreach($temp as $gene) { // OPENS foreach($temp as $gene) if (substr($gene, 0, 1) == \"(\") { // a list of 2 or more gene names OR\'ed together // remove the \"(\" and \")\" at both ends of the string. $gene = substr($gene, 1); $gene = substr($gene, 0, strlen($gene)-1); $genelist = preg_split(\"/ OR /\", $gene); $gename_r[] = $genelist; } else { // singleton $gename_r[] = array($gene); } } // CLOSES foreach($temp as $gene) } // CLOSES else part of if ( is_false(strpos($linestr, \"(\")) ) } // CLOSES if (left($linestr, 2) == \"GN\") // 0123456789012345678901234567890123456789 // SQ SEQUENCE XXXX AA; XXXXX MW; XXXXX CN; if ($linelabel == \"SQ\") { // OPENS if ($linelabel == \"SQ\") $linedata = rem_right($linedata); // XXXX AA, XXXX MW, XXXX CN $words = preg_split(\"/;/\", substr($linedata, 8)); $aa = preg_split(\"/\\s+/\", trim($words[0])); $aa_count = (int) trim($aa[0]); $mw = preg_split(\"/\\s+/\", trim($words[1])); $mol_wt = (int) trim($mw[0]); $cn = preg_split(\"/\\s+/\", trim($words[2])); $chk_no = trim($cn[0]); $chk_method = trim($cn[1]); $sequence = \"\"; while ( list($no, $linestr) = each($flines) ) { $linelabel = left($linestr, 2); if ($linelabel == \"//\") break; $linedata = intrim(trim($linestr)); $sequence .= $linedata; } } // CLOSES if ($linelabel == \"SQ\") } // CLOSES 1st (outermost) while ( list($no, $linestr) = each($flines) ) $seqobj = new seq(); $seqobj->id = $protein_name; $seqobj->seqlength = $length; $seqobj->moltype = $moltype; $seqobj->date = $create_date; $seqobj->accession = $accession[0]; array_shift($accession); $seqobj->sec_accession = $accession; $seqobj->source = $os_line; $seqobj->organism = $oc_line; $seqobj->sequence = $sequence; $seqobj->definition = $desc; $seqobj->keywords = $kw_r; $genbank_ref_r = array(); $inner_r = array(); foreach($ref_r as $key => $value) { $inner_r[\"REFNO\"] = $key; $db_id = $value[\"RX_BDN\"]; $inner_r[$db_id] = $value[\"RX_ID\"]; $inner_r[\"REMARKS\"] = $value[\"RP\"]; $inner_r[\"COMMENT\"] = $value[\"RC\"]; $inner_r[\"TITLE\"] = $value[\"RL\"]; $inner_r[\"JOURNAL\"] = $value[\"RL\"]; $inner_r[\"AUTHORS\"] = $value[\"RA\"]; $genbank_ref_r[] = $inner_r; } $seqobj->reference = $genbank_ref_r; $swiss = array(); $swiss[\"ID\"] = $protein_name; $swiss[\"PROT_NAME\"] = $protein_name; $swiss[\"MOL_TYPE\"] = $moltype; $swiss[\"PROT_SOURCE\"] = $protein_source; $swiss[\"DATA_CLASS\"] = $data_class; $swiss[\"LENGTH\"] = $length; $swiss[\"CREATE_DATE\"] = $create_date; $swiss[\"CREATE_REL\"] = $create_rel; $swiss[\"SEQUPD_DATE\"] = $sequpd_date; $swiss[\"SEQUPD_REL\"] = $sequpd_rel; $swiss[\"NOTUPD_DATE\"] = $notupd_date; $swiss[\"NOTUPD_REL\"] = $notupd_rel; // ACCESSION is an ARRAY. $swiss[\"ACCESSION\"] = $accession; $swiss[\"PRIM_AC\"] = $accession[0]; $swiss[\"DESC\"] = $desc; $swiss[\"IS_FRAGMENT\"] = $is_fragment; // KEYWORDS is an ARRAY. $swiss[\"KEYWORDS\"] = $kw_r; // ORGANISM is an ARRAY. $swiss[\"ORGANISM\"] = $os_line; $swiss[\"ORGANELLE\"] = $organelle; // FT_<keyword> is an ARRAY. process_ft($swiss, $ft_r); $swiss[\"AMINO_COUNT\"] = $aa_count; $swiss[\"MOLWT\"] = $mol_wt; $swiss[\"CHK_NO\"] = $chk_no; $swiss[\"CHK_METHOD\"] = $chk_method; $swiss[\"SEQUENCE\"] = $sequence; // GENE_NAME is an ARRAY. $swiss[\"GENE_NAME\"] = $gename_r; // ORG_CLASS is an ARRAY. $swiss[\"ORG_CLASS\"] = $oc_line; // REFERENCE is an ARRAY. $swiss[\"REFERENCE\"] = $ref_r; $seqobj->swissprot = $swiss; // ARRAY return $seqobj; } // CLOSES parse_swissprot() // parse_id() parses a GenBank data file and returns a Seq object containing parsed data. function parse_id($flines) { $seqarr = array(); $inseq_flag = false; $seqdata_flag = false; $accession_flag = false; $ref_array = array(); $feature_array = array(); $entry_ctr = 0; $ref_ctr = 0; $maxlength = 0; $minlength = 999999; $tot_seqlength = 0; while( list($lineno, $linestr) = each($flines) ) { // OPENS outermost while( list($lineno, $linestr) = each($flines) ) if (substr($linestr,0,5) == \"LOCUS\") { $entry_ctr++; $ref_ctr = 0; $ref_array = array(); // This is the beginning of a SEQUENCE ENTRY. $seqdata = \"\"; $seqobj = new seq(); $seqobj->id = trim(substr($linestr, 12, 16)); $seqobj->seqlength = trim(substr($linestr, 29, 11)) * 1; $tot_seqlength += $seqobj->seqlength; if ($seqobj->seqlength > $maxlength) $maxlength = $seqobj->seqlength; if ($seqobj->seqlength < $minlength) $minlength = $seqobj->seqlength; $seqobj->moltype = substr($linestr, 47, 6); if (substr($linestr, 44, 3) == \"ss-\") $seqobj->strands = \"SINGLE\"; elseif (substr($linestr, 44, 3) == \"ds-\") $seqobj->strands = \"DOUBLE\"; elseif (substr($linestr, 44, 3) == \"ms-\") $seqobj->strands = \"MIXED\"; $seqobj->topology = strtoupper(substr($linestr, 55, 8)); $seqobj->division = strtoupper(substr($linestr, 64, 3)); $seqobj->date = strtoupper(substr($linestr, 68, 11)); $inseq_flag = true; } if (trim(substr($linestr,0,10)) == \"BASE COUNT\") { if (count($feat_r) > 0) $seqobj->features = $feat_r; } if (trim(substr($linestr,0,12)) == \"FEATURES\") { // OPENS if (trim(substr($linestr,0,12)) == \"FEATURES\") // The REFERENCE section was present for this SEQUENCE ENTRY so we set REFERENCE attribute. if (count($ref_array) > 0) $seqobj->reference = $ref_array; $lastsubkey = \"\"; $feat_r = array(); $qual_r = array(); // Go to the next line. list($lineno, $linestr) = each($flines); // This loops through each line in the entire FEATURES SECTION. while( substr($linestr,0,10) != \"BASE COUNT\" ) { // FEATURES WHILE LOOP $label = trim(substr($linestr,0,21)); $data = trim(substr($linestr,21)); if (strlen($label) != 0) { // At the beginning of a new SUBKEY. $subkey = $label; // Add/save the qualifier array (qual_r) of the previous SUBKEY to our big feat_r array. if (count($qual_r) > 0) { $feat_r[$lastsubkey] = $qual_r; $qual_r = array(); } $qual = $subkey; $qual_r[$qual] = \"\"; $qual_ctr = 0; do { // QUALIFIER WHILE LOOP $qual_ctr++; $qual_r[$qual] .= \" \" . $data; list($lineno, $linestr) = each($flines); $label = trim(substr($linestr,0,21)); $data = trim(substr($linestr,21)); } while( is_blank($label) and !(isa_qualifier($data)) ); if (!(is_blank($label))) { $lastsubkey = $subkey; $subkey = $label; } } else { // we are inside a subkey section but on the 2nd, 3rd, nth line which have blank LABELS. if (isa_qualifier($data)) { $wordarray = preg_split(\"/=/\", $data); $qual = $wordarray[0]; $data = $wordarray[1]; $qual_r[$qual] = \"\"; $qual_ctr = 0; do { // QUALIFIER WHILE LOOP $qual_ctr++; $qual_r[$qual] .= \" \" . $data; list($lineno, $linestr) = each($flines); $label = trim(substr($linestr,0,21)); $data = trim(substr($linestr,21)); } while( is_blank($label) and !(isa_qualifier($data)) ); if (!(is_blank($label))) { $lastsubkey = $subkey; $subkey = $label; } } } // ELSE PART of if (strlen($subkey) != 0) } // FEATURES WHILE LOOP if (count($qual_r) > 0) { $feat_r[$lastsubkey] = $qual_r; $qual_r = array(); } prev($flines); } // CLOSES if (trim(substr($linestr,0,12)) == \"FEATURES\") if (substr($linestr,0,10) == \"DEFINITION\") { $wordarray = explode(\" \", $linestr); array_shift($wordarray); $seqobj->definition = implode(\" \", $wordarray); } if ($inseq_flag == TRUE) { // OPENS if ($inseq_flag == TRUE) if (trim(substr($linestr, 0, 12)) == \"REFERENCE\") { // at this point, we are at the line with REFERENCE x (base y of z) in it. $wordarray = preg_split(\"/\\s+/\", trim(substr($linestr,12))); $ref_rec = array(); $ref_rec[\"REFNO\"] = $wordarray[0]; array_shift($wordarray); $ref_rec[\"BASERANGE\"] = implode(\" \", $wordarray); $lastsubkey = \"\"; $subkey_lnctr = 0; while( list($lineno, $linestr) = each($flines) ) { $subkey = trim(substr($linestr,0,12)); // If current subkey is blank string, then this is a continuation of the last subsection. if (strlen($subkey) == 0) $subkey = $lastsubkey; // If we are at the next subkey section (e.g. lastsubkey was AUTHORS, and current is TITLE). if ($subkey != $lastsubkey) $subkey_lnctr = 0; switch ($subkey) { case \"AUTHORS\": $subkey_lnctr++; $wordarray = preg_split(\"/\\s+/\", trim(substr($linestr,12))); // we remove comma at the end of a name, and the element \"and\". $newarray = array(); foreach($wordarray as $authname) { if (strtoupper($authname) != \"AND\") { if (substr($authname, strlen($authname)-1, 1) == \",\") $authname = substr($authname, 0, strlen($authname)-1); $newarray[] = $authname; } } if ($subkey_lnctr == 1) $ref_rec[\"AUTHORS\"] = $newarray; else $ref_rec[\"AUTHORS\"] = array_merge($ref_rec[\"AUTHORS\"], $newarray); break; case \"TITLE\": $subkey_lnctr++; if ($subkey_lnctr == 1) $ref_rec[\"TITLE\"] = trim(substr($linestr,12)); else $ref_rec[\"TITLE\"] .= \" \" . trim(substr($linestr,12)); break; case \"JOURNAL\": $subkey_lnctr++; if ($subkey_lnctr == 1) $ref_rec[\"JOURNAL\"] = trim(substr($linestr,12)); else $ref_rec[\"JOURNAL\"] .= \" \" . trim(substr($linestr,12)); break; case \"MEDLINE\": $ref_rec[\"MEDLINE\"] = substr($linestr, 12, 8); break; case \"PUBMED\": $ref_rec[\"PUBMED\"] = substr($linestr, 12, 8); break; case \"REMARK\": $subkey_lnctr++; if ($subkey_lnctr == 1) $ref_rec[\"REMARK\"] = trim(substr($linestr,12)); else $ref_rec[\"REMARK\"] .= \" \" . trim(substr($linestr,12)); break; case \"COMMENT\": $subkey_lnctr++; if ($subkey_lnctr == 1) $ref_rec[\"COMMENT\"] = trim(substr($linestr,12)); else $ref_rec[\"COMMENT\"] .= \" \" . trim(substr($linestr,12)); break; } if ($subkey == \"FEATURES\") { prev($flines); break; } if ($subkey == \"REFERENCE\") { $ref_ctr++; prev($flines); break; } $lastsubkey = $subkey; } array_push($ref_array, $ref_rec); } if (trim(substr($linestr, 0, 12)) == \"SOURCE\") { // For now, assume a single-line SOURCE field. $seqobj->source = substr($linestr, 12); } if (trim(substr($linestr, 0, 12)) == \"SEGMENT\") { $seqobj->segment = substr($linestr, 12); $wordarray = preg_split(\"/\\s+/\", trim(substr($linestr,12))); $seqobj->segment_no = $wordarray[0]; $seqobj->segment_count = $wordarray[2]; } // For now, assume that KEYWORDS field consists of exactly one line. if (trim(substr($linestr, 0, 12)) == \"KEYWORDS\") { $wordarray = preg_split(\"/\\s+/\", trim($linestr)); array_shift($wordarray); $wordarray = preg_split(\"/;+/\", implode(\" \", $wordarray)); if ($wordarray[0] != \".\") $seqobj->keywords = $wordarray; } if (substr($linestr, 0, 7) == \"VERSION\") { // Assume that VERSION line is made up of exactly 2 or 3 tokens. $wordarray = preg_split(\"/\\s+/\", trim($linestr)); $seqobj->version = $wordarray[1]; if (count($wordarray) == 3) $seqobj->ncbi_gi_id = $wordarray[2]; $accession_flag = false; } if ($accession_flag == TRUE) { // 2nd, 3rd, etc. line of ACCESSION field. $wordarray = preg_split(\"/\\s+/\", trim($linestr)); $this->sec_accession = array_merge($this->sec_accession, $wordarray); } if (substr($linestr,0,9) == \"ACCESSION\") { $wordarray = preg_split(\"/\\s+/\", trim($linestr)); $seqobj->accession = $wordarray[1]; array_shift($wordarray); array_shift($wordarray); $seqobj->sec_accession = $wordarray; $accession_flag = true; } if (substr($linestr,0,10) == \" ORGANISM\") { $seqobj->organism = substr($linestr,12); } if (($seqdata_flag == true) && (substr($linestr,0,2) != \"//\")) { $wordarray = explode(\" \", trim($linestr)); array_shift($wordarray); $seqline = implode(\"\", $wordarray); $seqdata .= $seqline; } if (substr($linestr,0,6) == \"ORIGIN\") $seqdata_flag = true; if (substr($linestr,0,2) == \"//\") { $seqobj->sequence = $seqdata; $seqarr[$this->id] = $this; $seqdata_flag = false; $inseq_flag = false; break; } } // CLOSES if ($inseq_flag == TRUE) } // CLOSES outermost while( list($lineno, $linestr) = each($flines) ) $seqobj->seqarray = $seqarr; return $seqobj; } // Closes parse_id() constructor function definition // open() opens or prepares the SeqDB for processing. Opposite of close(). function open($dbname) { if (file_exists($dbname . \".idx\") == FALSE) die(\"ERROR: Index file $dbname.IDX does not exist!\"); if (file_exists($dbname . \".dir\") == FALSE) die(\"ERROR: Index file $dbname.DIR does not exist!\"); $this->dbname = $dbname; $this->data_fn = $dbname . \".idx\"; $this->dir_fn = $dbname . \".dir\"; $this->seqptr = 0; } // close() closes the SeqDB database after we\'re through using it. Opposite of open() method. function close() { // // Close simply assigns null values to attributes of the seqdb() object. // Methods like fetch would not function properly if these values are null. $this->dbname = \"\"; $this->data_fn = \"\"; $this->dir_fn = \"\"; $this->seqptr = -1; } /* SeqDB() is the constructor method for the SeqDB class. It does many things like create and/or read a database\'s index files, initialize certain SeqDB properties, etc. Syntax: $seqdb = new seqdb($dbname, $dbformat, $file1, $file2, ...); Behavior: if $dbname exists and user gave no specific values for $file1, $file2, ... then seqdb() object USES/OPENS existing database (index files). if $dbname exists and user gave specific values for $file1, $file2, ... then seqdb() object OVERWRITES existing database (index files). if $dbname does not exist, then seqdb() object CREATES new database. even if $file1, $file2, ... are not specified. We provide the create() method to explicitly create a new database. We provide the use() or open() method to explicitly use an existing database. */ function SeqDB() { // Get all the arguments passed to this function. $args = func_get_args(); $dbname = $args[0]; $dbformat = strtoupper($args[1]); if (strlen($dbformat) == 0) $dbformat = \"GENBANK\"; $this->dbformat = $dbformat; $datafile = array(); for($i = 2; $i < count($args); $i++) $datafile[] = $args[$i]; /* db exists fileX args ACTION TESTED Y Y create okay Y N use N Y create okay N N create okay */ // if user provided specific values for $file1, $file2, ... parameters. if ((file_exists($dbname)) and (count($datafile) > 0)) { // For now, assume USING/OPENING a database is to be done in READ ONLY MODE. $this->open($dbname); } else { // March 26, 2003: I switched the 2 lines below with // the line: $this->open($dbname); to avoid die-ing with // the error message: \"ERROR: Index file does not exist!\" $fp = fopen($dbname . \".idx\", \"w+\"); $fpdir = fopen($dbname . \".dir\", \"w+\"); // Creates blank data and directory index files, and sets seqptr to 0, etc. $this->open($dbname); // if user did not provide any datafile name. if (count($datafile) == 0) return; $temp_r = array(); // Build our *.DIR file foreach($datafile as $fileno=>$filename) { $outline = \"$fileno $filename\\n\"; fputs($fpdir, $outline); // Automatically create an index file containing info across all data files. $flines = file($filename); $totlines = count($flines); while( list($lineno, $linestr) = each($flines) ) { // if (substr($linestr,0,5) == \"LOCUS\") if (at_entrystart($linestr, $dbformat)) { // $current_id = trim(substr($linestr, 12, 16)); $current_id = get_entryid($flines, $linestr, $dbformat); $outline = \"$current_id $fileno $lineno\\n\"; // Put entries in an array first, sort them, then write to *.IDX file. // temp_r = (\"AB1234\" => (\"AB1234\", 1, 12), \"BC4321\" => ... ); $temp_r[$current_id] = array($current_id, $fileno, $lineno); } } // Sort our array by its keys. ksort($temp_r); } // Build our *.IDX array. $this->seqcount = count($temp_r); foreach($temp_r as $seqid=>$line_r) { $outline = $line_r[0] . \" \" . $line_r[1] . \" \" . $line_r[2] . \"\\n\"; $fio = fputs($fp, $outline); } } fclose($fp); fclose($fpdir); } // CLOSES definition of SeqDB constructor function. } // CLOSES definition of SEQDB CLASS. ?>