home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / Molecule.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  11.8 KB  |  416 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: Molecule.php,v 1.4 2003/05/13 01:18:17 jmcastagnetto Exp $
  20. //
  21.  
  22. require_once "Science/Chemistry.php";
  23. require_once "Science/Chemistry/Atom.php";
  24.  
  25. /**
  26.  * Base class representing a Molecule
  27.  *
  28.  * @author  Jesus M. Castagnetto <jmcastagnetto@php.net>
  29.  * @version 1.0
  30.  * @access  public
  31.  * @package Science_Chemistry
  32.  */
  33. class Science_Chemistry_Molecule {
  34.  
  35.     /**
  36.      * Molecule name
  37.      *
  38.      * @var     string
  39.      * @access  public
  40.      */
  41.     var $name = "";
  42.  
  43.     /**
  44.      * Number of atoms in the molecule
  45.      * 
  46.      * @var     integer
  47.      * @access  public
  48.      * @see     initMolecule()
  49.      */
  50.     var $num_atoms = 0;
  51.  
  52.     /**
  53.      * Array of atom objects in the molecule
  54.      *
  55.      * @var     array
  56.      * @access  private
  57.      * @see     initMolecule()
  58.      */
  59.     var $atoms = array();
  60.  
  61.     /**
  62.      * Atom-Atom distance matrix
  63.      *
  64.      * @var     array
  65.      * @access  private
  66.      * @see     calcDistanceMatrix()
  67.      */
  68.     var $dist_matrix = array();
  69.  
  70.     /**
  71.      * Atom-Atom connection (bond) table
  72.      *
  73.      * @var     array
  74.      * @access  private
  75.      * @see     calcConnectionTable()
  76.      */
  77.     var $conn_table = array();
  78.  
  79.     /**
  80.      * Distance cutoff for bond estimation
  81.      *
  82.      * @var     float
  83.      * @access  private
  84.      * @see     setBondCutoff()
  85.      * @see     getBondCutoff()
  86.      * @see     calcConnectionTable()
  87.      */
  88.     var $BONDCUTOFF = 1.8;
  89.  
  90.     /**
  91.      * Constructor for the class, requires a molecule name
  92.      * and an optional array of Science_Chemistry_Atom objects
  93.      * 
  94.      * @param   string  $name
  95.      * @param   optional    array   $atoms
  96.      * @return  object  Science_Chemistry_Molecule
  97.      * @access  public
  98.      * @see     $name
  99.      * @see     initMolecule()
  100.      */
  101.     function Science_Chemistry_Molecule($name, $atoms="") {
  102.         if ($name)
  103.             $this->name = $name;
  104.         else
  105.             return null;
  106.         if ($atoms && is_array($atoms))
  107.             if (!$this->initMolecule($atoms))
  108.                 return null;
  109.     }
  110.  
  111.     /**
  112.      * Initializes the array of Science_Chemistry_Atom objects
  113.      * 
  114.      * @param   array   $atoms
  115.      * @return  boolean
  116.      * @access  public
  117.      * @see     $num_atoms
  118.      * @see     $atoms
  119.      * @see     addAtom()
  120.      */
  121.     function initMolecule($atoms) {
  122.         if (is_array($atoms)) {
  123.             for ($i=0; $i=count($atoms); $i++) {
  124.                 if (!$this->addAtom($atoms[$i]))
  125.                     return false;
  126.             }
  127.             return true;
  128.         } else {
  129.             return false;
  130.         }
  131.     }
  132.  
  133.     /**
  134.      * Adds a Science_Chemistry_Atom object to the list of atoms in the molecule
  135.      * 
  136.      * @param   object  Science_Chemistry_Atom   $atom
  137.      * @return  boolean
  138.      * @access  public
  139.      * @see     initMolecule()
  140.      */
  141.     function addAtom($atom) {
  142.         if (Science_Chemistry_Atom::isAtom($atom)) {
  143.             $this->atoms[] = $atom;
  144.             $this->num_atoms++;
  145.             // unset the distance matrix and 
  146.             // connection table if they are not empty
  147.             // so next time either one is requested
  148.             // it gets calculated anew
  149.             if (!empty($this->dist_matrix))
  150.                 $this->dist_matrix = array();
  151.             if (!empty($this->conn_table))
  152.                 $this->conn_table = array();
  153.             return true;
  154.         } else {
  155.             return false;
  156.         }
  157.     }
  158.  
  159.  
  160.     /**
  161.      * Returns an array of Atom objects
  162.      *
  163.      * @return  array
  164.      * @access  public
  165.      * @see     $atoms
  166.      */
  167.     function getAtoms() {
  168.         return $this->atoms;
  169.     }
  170.  
  171.     /**
  172.      * Checks if the object is an instance of Science_Chemistry_Molecule
  173.      *
  174.      * @param   object  Science_Chemistry_Molecule $obj
  175.      * @return  boolean
  176.      * @access  public
  177.      */
  178.     function isMolecule($obj) {
  179.         return  (is_object($obj) && 
  180.                  (strtolower(get_class($obj)) == strtolower("Science_Chemistry_Molecule") ||
  181.                   is_subclass_of($obj, strtolower("Science_Chemistry_Molecule")))
  182.                 );
  183.     }
  184.  
  185.     /**
  186.      * Returns a string representation of the molecule  as a XYZ-format file
  187.      * Alias of toXYZ()
  188.      *
  189.      * @return  string
  190.      * @access  public
  191.      * @see toXYZ()
  192.      */
  193.     function toString() {
  194.         return $this->toXYZ();
  195.     }
  196.  
  197.     /**
  198.      * Returns a string representation of the molecule  as a XYZ-format file
  199.      *
  200.      * @return  string
  201.      * @access  public
  202.      * @see toString()
  203.      */
  204.     function toXYZ() {
  205.         if (!$this->atoms)
  206.             return false;
  207.         $out[] = $this->num_atoms;
  208.         $out[] = $this->name;
  209.         reset($this->atoms);
  210.         for ($i=0; $i<$this->num_atoms; $i++)
  211.             $out[] = $this->atoms[$i]->toString();
  212.         return implode("\n",$out)."\n";
  213.     }
  214.  
  215.     /**
  216.      * Returns a CML representation of the molecule
  217.      * Accepts an optional id, and a flag to signal
  218.      * printing of the connection table
  219.      *
  220.      * @param   optional    string  $id
  221.      * @param   optional    boolean $connect
  222.      * @return  string
  223.      * @access  public
  224.      */
  225.     function toCML($title="molecule", $id="mol1", $connect=false) {
  226.         $out = " <molecule title=\"$title\" id=\"$id\">\n";
  227.         $out .= "  <string title=\"name\">".$this->name."</string>\n";
  228.         $out .= "  <list title=\"atoms\">\n";
  229.         for ($i=0; $i<$this->num_atoms; $i++)
  230.             $out .= $this->atoms[$i]->toCML($i+1);
  231.         $out .= "  </list>\n";
  232.         if ($connect) {
  233.             // calculate the connection table if needed
  234.             // and short-circuit if we cannot do that
  235.             if (empty($this->conn_table)) 
  236.                 if (!$this->calcConnectionTable()) {
  237.                     $out .= " </molecule>\n";
  238.                     return $out;
  239.                 }
  240.             $out .= "  <list title=\"connections\">\n";
  241.             for ($i=0; $i < count($this->conn_table); $i++) {
  242.                 $tmp = array();
  243.                 foreach ($this->conn_table[$i] as $atomid=>$flag) {
  244.                     if ($flag)
  245.                         $tmp[] = $atomid + 1;
  246.                 }
  247.                 if (!empty($tmp)) {
  248.                     $out .= "   <list title=\"connect\" id=\"".($i + 1)."\">";
  249.                     $out .= implode(" ", $tmp)."</list>\n";
  250.                 }
  251.             }
  252.             $out .= "  </list>\n";
  253.         }
  254.         $out .= " </molecule>\n";
  255.         return $out;
  256.     }
  257.  
  258.     
  259.     /**
  260.      * Sets the distance cutoff for bond determination
  261.      *
  262.      * @param   float   $cutoff
  263.      * @return  boolean
  264.      * @access  public
  265.      * @see     $BONDCUTOFF
  266.      * @see     getBondCutoff()
  267.      * @see     calcConnectionTable()
  268.      */
  269.     function setBondCutoff($cutoff) {
  270.         if ((float)$cutoff > 0.0) {
  271.             $this->BONDCUTOFF = (float)$cutoff;
  272.             return true;
  273.         } else {
  274.             return false;
  275.         }
  276.     }
  277.  
  278.     /**
  279.      * Returns the bond cutoff uses to determine bonds
  280.      * 
  281.      * @return  float
  282.      * @access  public
  283.      * @see     $BONDCUTOFF
  284.      * @see     setBondCutoff()
  285.      * @see     calcConnectionTable()
  286.      */
  287.     function getBondCutoff() {
  288.         return $this->BONDCUTOFF;
  289.     }
  290.  
  291.     /**
  292.      * Calculates the atom-atom distance matrix in Angstroms
  293.      *
  294.      * @return  boolean
  295.      * @access  public
  296.      */
  297.     function calcDistanceMatrix() {
  298.         if (empty($this->atoms))
  299.             return false;
  300.         $this->dist_matrix = array();
  301.         for ($i=0; $i < $this->num_atoms; $i++)
  302.             for ($j=0; $j < $this->num_atoms; $j++) {
  303.                 if ($i == $j) {
  304.                     $this->dist_matrix[$i][$j] = 0.0;
  305.                 } elseif ($i < $j) {
  306.                     $this->dist_matrix[$i][$j] = $this->atoms[$i]->distance($this->atoms[$j]);
  307.                 }
  308.             }
  309.         return true;
  310.     }
  311.  
  312.     /**
  313.      * Prints the atom-atom distance matrix
  314.      *
  315.      * @return  string
  316.      * @access  public
  317.      */
  318.     function printDistanceMatrix() {
  319.         if (empty($this->dist_matrix))
  320.             if(!$this->calcDistanceMatrix())
  321.                 return false;
  322.         $dmat = &$this->dist_matrix;
  323.         echo "# Atom-Atom Distance Matrix:\n";
  324.         for ($i=0; $i < $this->num_atoms; $i++)
  325.             echo "\t".($i+1);
  326.         for ($i=0; $i < $this->num_atoms; $i++) {
  327.             echo "\n".($i+1);
  328.             for ($j=0; $j < $this->num_atoms; $j++)
  329.                 if (!isset($dmat[$i][$j])) {
  330.                     echo "\t";
  331.                 } else {
  332.                     printf("\t%.4f",$dmat[$i][$j]);
  333.                 }
  334.         }
  335.         echo "\n";
  336.         return true;
  337.     }
  338.  
  339.     /**
  340.      * Returns the atom-atom distance matrix
  341.      *
  342.      * @return  array
  343.      * @access  public
  344.      */
  345.     function getDistanceMatrix() {
  346.         if (empty($this->dist_matrix))
  347.             if (!$this->calcDistanceMatrix())
  348.                 return false;
  349.         return $this->dist_matrix;
  350.     }
  351.  
  352.     /**
  353.      * Calculates the connection table for the molecule
  354.      *
  355.      * @return  boolean
  356.      * @access  public
  357.      */
  358.     function calcConnectionTable(){
  359.         if (empty($this->dist_matrix))
  360.             if (!$this->calcDistanceMatrix())
  361.                 return false;
  362.         $dmat = &$this->dist_matrix;
  363.         for ($i=0; $i < $this->num_atoms; $i++)
  364.             for ($j=($i+1); $j < $this->num_atoms; $j++)
  365.                 $this->conn_table[$i][$j] = ($dmat[$i][$j] <= $this->BONDCUTOFF);
  366.         return true;
  367.     }
  368.  
  369.     /**
  370.      * Prints the molecule's connection table
  371.      *
  372.      * @return  boolean
  373.      * @access  public
  374.      */
  375.     function printConnectionTable() {
  376.         if (empty($this->conn_table))
  377.             if (!$this->calcConnectionTable())
  378.                 return false;
  379.         printf("# Connection Table: (cutoff = %.4f Angstroms)\n", $this->BONDCUTOFF);
  380.         for ($i=0; $i < $this->num_atoms; $i++)
  381.             for ($j=($i+1); $j < $this->num_atoms; $j++)
  382.                 if ($this->conn_table[$i][$j]) {
  383.                     echo $this->atoms[$i]->element.($i+1)."\t";
  384.                     echo $this->atoms[$j]->element.($j+1)."\n";
  385.                 }
  386.         return true;
  387.     }
  388.  
  389.     /**
  390.      * Returns an array of connected atoms and their bond distance
  391.      * e.g. array ( array ($atomobj1, $atomobj2, $distance ), ... )
  392.      * 
  393.      * @return  array
  394.      * @access  public
  395.      */
  396.     function getConnectionTable() {
  397.         if (empty($this->conn_table))
  398.             if (!$this->calcConnectionTable())
  399.                 return false;
  400.         $ct = 0; $ctable=array();
  401.         for ($i=0; $i < $this->num_atoms; $i++)
  402.             for ($j=($i+1); $j < $this->num_atoms; $j++)
  403.                 if ($this->conn_table[$i][$j]) {
  404.                     $ctable[$ct] = array ($this->atoms[$i], $this->atoms[$j],
  405.                                     $this->dist_matrix[$i][$j]);
  406.                     $ct++;
  407.                 }
  408.        return $ctable; 
  409.     }
  410.  
  411. } // end of class Science_Chemistry_Molecule
  412.  
  413.  
  414. // vim: expandtab: ts=4: sw=4
  415. ?>
  416.