home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / PDBParser.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  9.1 KB  |  268 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Jesus M. Castagnetto <jmcastagnetto@php.net>                |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: PDBParser.php,v 1.4 2003/01/04 11:56:25 mj Exp $
  20. //
  21.  
  22. /**
  23.  * A self-contained class to parse a PDB file into an array of residues
  24.  * each containing an array of atoms
  25.  * <br>
  26.  * Useful when dealing with big PDB files, where using the Science_Chemistry_PDBFile
  27.  * class will generate out of memory errors.
  28.  *
  29.  * @author  Jesus M. Castagnetto <jmcastagnetto@php.net>
  30.  * @version 1.0
  31.  * @access  public
  32.  * @package Science_Chemistry
  33.  * @see     Science_Chemistry_PDBFile
  34.  */
  35. class Science_Chemistry_PDBParser {
  36.  
  37.     /**
  38.      * PDB ID
  39.      *
  40.      * @var     string
  41.      * @access   private
  42.      */
  43.     var $pdb;
  44.  
  45.     /**
  46.      * Full path to PDB file
  47.      *
  48.      * @var     string
  49.      * @access  private
  50.      */
  51.     var $file;
  52.  
  53.     /**
  54.      * PDB file's date
  55.      *
  56.      * @var     date
  57.      * @access  private
  58.      */
  59.     var $date;
  60.  
  61.     /**
  62.      * PDB macromolecule(s) class
  63.      *
  64.      * @var     string
  65.      * @access  private
  66.      */
  67.     var $class;
  68.  
  69.     /**
  70.      * Array of macromolecules
  71.      *
  72.      * @var     array
  73.      * @access  private
  74.      */
  75.     var $macromolecules;
  76.  
  77.     /**
  78.      * Number of macromolecules
  79.      *
  80.      * @var     int
  81.      * @access  private
  82.      */
  83.     var $num_macromolecules;
  84.  
  85.     /**
  86.      * Constructor for the class, requires a PDB filename
  87.      * 
  88.      * @param   string  $filename   PDB filename
  89.      * @param   boolean $multi  whether to parse all models in a multi-model file
  90.      * @param   boolean $meta   whether to store the PDB file meta information
  91.      * @param   boolean $full   whether to store the full set of fields per atom
  92.      * @return  object  PDBParser
  93.      * @access  public
  94.      * @see     parseResidues()
  95.      */
  96.     function Science_Chemistry_PDBParser($filename, $multi=false, $meta=false, $full=false) {
  97.         if (!file_exists($filename))
  98.             return null;
  99.         list($pdb,) = explode(".",basename($filename));
  100.         $this->pdb = $pdb;
  101.         $this->file = realpath($filename);
  102.         $arr = file($filename);
  103.         // parsing the PDB file
  104.         $month = array (
  105.                 "JAN" => "01", "FEB" => "02", "MAR" => "03",
  106.                 "APR" => "04", "MAY" => "05", "JUN" => "06",
  107.                 "JUL" => "07", "AUG" => "08", "SEP" => "09",
  108.                 "OCT" => "10", "NOV" => "11", "DEC" => "12"
  109.                 );
  110.         $header_re = "/^HEADER[[:space:]]+(([^[:space:]]+ )+)[[:space:]]+";
  111.         $header_re .= "([0-9]{2}-[A-Z]{3}-[0-9]{2,4})[[:space:]]+[A-Z0-9]{4}/";
  112.  
  113.         if (preg_match($header_re, $arr[0], &$regs)) {
  114.             $this->class = trim($regs[1]);
  115.             // put date in a more standard format
  116.             $tmp = explode("-", $regs[3]);
  117.             if ($tmp[2] <= 23)
  118.                 $year = 2000 + (int)$tmp[2];
  119.             else
  120.                 $year = 1900 + (int)$tmp[2];
  121.             $this->date = $year."-".$month[$tmp[1]]."-".$tmp[0];
  122.         }
  123.         
  124.         $flag = "nomodel";
  125.         $tmparr = array();
  126.         for ($i=0; $i < count($arr); $i++) {
  127.             if (!trim($arr[$i]))
  128.                 continue;
  129.             $rectype = strtok($arr[$i]," ");
  130.             
  131.             // check if we have multi-model file
  132.             if ($rectype == "MODEL")
  133.                 continue;
  134.  
  135.             // did we get a multi-model file and are parsing the end
  136.             // of a model, if so, end parsing altogether
  137.             if ($rectype == "ENDMDL") {
  138.                 if ($multi) {
  139.                     $this->macromolecules[] = $this->parseResidues(&$tmparr, $full);
  140.                     $this->num_macromolecules++; // = count($this->macromolecules);
  141.                     $tmparr = array();
  142.                 } else {
  143.                     break;
  144.                 }
  145.                 continue;
  146.             }
  147.  
  148.             // accumulate atom records, put the rest into the meta array
  149.             if ($rectype == "ATOM" || $rectype == "HETATM")
  150.                 $tmparr[] = $arr[$i];
  151.             elseif ($meta)
  152.                 $this->meta[$rectype][] = $arr[$i];
  153.         }
  154.         if (!empty($tmparr)) {
  155.             $this->macromolecules[] = $this->parseResidues(&$tmparr, $full);
  156.             $this->num_macromolecules++; // = count($this->macromolecules);
  157.         }
  158.     }
  159.  
  160.     /**
  161.      * Makes the array of residues in the macromolecule
  162.      *
  163.      * @param   array   $records
  164.      * @param   boolean $full   whether to store the full set of fields per atom
  165.      * @see     parseFile()
  166.      * @see     parseAtom()
  167.      */
  168.     function parseResidues($records, $full) {
  169.         $curr_res_id = "";
  170.         $residues = array();
  171.         $res_atoms = array();
  172.         for ($i=0; $i< count($records); $i++) {
  173.             $atomrec =& $records[$i];
  174.             $res_name = trim(substr($atomrec,17,3));
  175.             $chain = trim(substr($atomrec,21,1));
  176.             $seq_num = (int) trim(substr($atomrec,22,4));
  177.             $res_id = $res_name.":".$seq_num.":".$chain;
  178.             
  179.             //if ($i == 0)
  180.               //  $curr_res_id = $res_id;
  181.  
  182.             if ($res_id == $curr_res_id) {
  183.                 $res_atoms[] = $atomrec;
  184.                 if ($i != (count($records) - 1))
  185.                     continue;
  186.             }
  187.  
  188.             if (($res_id != $curr_res_id) || 
  189.                 ($i == (count($records) - 1))
  190.                 ) {
  191.                 if (!empty($res_atoms)) {
  192.                     for ($j=0; $j < count($res_atoms); $j++) {
  193.                         $temp = $this->parseAtom($res_atoms[$j], $full, &$atomname);
  194.                         $residues[$curr_res_id][$atomname] = $temp;
  195.                     }
  196.                 }
  197.                 $curr_res_id = $res_id;
  198.                 $res_atoms = array($atomrec);
  199.             }
  200.         }
  201.         return $residues;
  202.     }
  203.  
  204.     /**
  205.      * Parses an atom record into an associative array
  206.      *
  207.      * @param   string  $atomrec    PDB atom record
  208.      * @param   boolean $full   whether to store the full set of fields per atom
  209.      * @see     parseResidues()
  210.      */
  211.     function parseAtom($atomrec, $full, &$atomname) {
  212.         $atom = array();
  213.         // process PDB atom record
  214.         // no error checking, assumes correct and standard record
  215.         $atom["RecName"] = trim(substr($atomrec,0,6));
  216.         $atom["SerNum"] = (int) trim(substr($atomrec,6,5));
  217.         $atom["AtomName"] = trim(substr($atomrec,12,4));
  218.         $atomname = $atom["AtomName"];
  219.         if ($full) {
  220.             $atom["AltLoc"] = trim(substr($atomrec,16,1));
  221.             $atom["ResName"] = trim(substr($atomrec,17,3));
  222.             $atom["ChainID"] = trim(substr($atomrec,21,1));
  223.             $atom["ResSeqNum"] = (int) trim(substr($atomrec,22,4));
  224.             $atom["InsCode"] = trim(substr($atomrec,26,1));
  225.             $atom["Occupancy"] = (float) trim(substr($atomrec,54,6));
  226.             $atom["TempFactor"] = (float) trim(substr($atomrec,60,6));
  227.             $atom["SegmentID"] = trim(substr($atomrec,72,4));
  228.             $atom["Charge"] = (float)trim(substr($atomrec,78,2));
  229.             $atom["Element"] = trim(substr($atomrec,76,2));
  230.         }
  231.         $atom["X"] = (double) trim(substr($atomrec,30,8));
  232.         $atom["Y"] = (double) trim(substr($atomrec,38,8));
  233.         $atom["Z"] = (double) trim(substr($atomrec,46,8));
  234.         return $atom;
  235.     }
  236.  
  237.     /**
  238.      * Returns an array of residues with a particular name
  239.      * from the indicated macromolecule index
  240.      *
  241.      * @param   integer $macromol   Index of the macromolecule in the $macromolecules array
  242.      * @param   string  $resnam     Residue name, e.g. HIS, CYS, etc.
  243.      * @return  array   list of residues with the requested name
  244.      * @access  public
  245.      * @see     $macromolecules
  246.      */
  247.     function getResidueList ($macromol, $resname) {
  248.         $mol =& $this->macromolecules[$macromol];
  249.         $reslist = array();
  250.         if (!$mol)
  251.             return $reslist;
  252.         foreach($mol as $resid=>$atoms) {
  253.             list($curr_res_name,,) = explode(":",$resid);
  254.         //    echo $curr_res_name."***\n";
  255.             if ($curr_res_name == $resname)
  256.                 $reslist[$resid] = $atoms;
  257.             else
  258.                 continue;
  259.             
  260.         }
  261.         return $reslist;
  262.     }
  263.  
  264. } // end of PDBParser
  265.  
  266. // vim: expandtab: ts=4: sw=4
  267. ?>
  268.