/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* Last commit: $Rev: 1210 $ by $Author: glycoslave $ on $Date:: 2009-06-12 #$
*/
package org.eurocarbdb.resourcesdb.atom;
import java.util.ArrayList;
import java.util.List;
import org.eurocarbdb.resourcesdb.ResourcesDbException;
import org.eurocarbdb.resourcesdb.monosaccharide.MonosaccharideException;
import org.eurocarbdb.resourcesdb.util.NumberUtils;
/**
* Class to store atom properties
* @author Thomas Lütteke
*
*/
public class Atom implements Cloneable {
private int id = 0;
private int dbId = 0;
private AtomTemplate template = null;
private Periodic element = null;
private Isotope isotope = null;
private String name = null;
private String mol2Type = null;
private Double charge = null;
private List<AtomConnection> connectionList = null;
private boolean deletedInLinkage = false;
//*** coordinates: ***
private Double x = null;
private Double y = null;
private Double z = null;
//*****************************************************************************
//*** constructors: ***********************************************************
//*****************************************************************************
public Atom() {
this.init();
}
public Atom(Periodic el) {
this.init();
this.setElement(el);
}
public Atom(String elSym) throws ResourcesDbException {
this.init();
this.setElement(Periodic.getElementBySymbol(elSym));
}
public Atom(AtomTemplate tmpl) {
this.init();
this.setTemplate(tmpl);
this.setElement(tmpl.getElement());
this.setMol2Type(tmpl.getMol2Type());
}
public Atom(int id, Periodic el, String name) {
this.init();
this.setId(id);
this.setElement(el);
this.setName(name);
}
//*****************************************************************************
//*** getters/setters: ********************************************************
//*****************************************************************************
/**
* Get the atom id
* @return the id
*/
public int getId() {
return this.id;
}
/**
* Set the atom id
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* Get the atom template
* @return the template
*/
public AtomTemplate getTemplate() {
return template;
}
/**
* Set the atom template
* @param tmpl the template to set
*/
public void setTemplate(AtomTemplate tmpl) {
this.template = tmpl;
}
public void setTemplateAndInit(AtomTemplate tmpl) {
this.template = tmpl;
this.setElement(tmpl.getElement());
this.setName(tmpl.getElement().getSymbol());
this.setMol2Type(tmpl.getMol2Type());
}
/**
* Get the atom name
* @return the name
*/
public String getName() {
return this.name;
}
/**
* Set the atom name
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* Get this atom's mol2 type
* @return the mol2 type
*/
public String getMol2Type() {
if(this.mol2Type == null) {
this.setMol2Type(Mol2Type.getMol2Type(this));
}
return this.mol2Type;
}
/**
* Set this atom's type for use in mol2 files
* @param type the mol2 atom type to set
*/
public void setMol2Type(String type) {
this.mol2Type = type;
}
/**
* Get the atom's element
* @return the element
*/
public Periodic getElement() {
return this.element;
}
/**
* Set the atom's element
* @param element the element to set
*/
public void setElement(Periodic element) {
this.element = element;
}
/**
* Get the periodic symbol of the element of this atom
* @return the periodic symbol
*/
public String getElementSymbol() {
if(this.getElement() == null) {
return(null);
} else {
return(this.getElement().getSymbol());
}
}
/**
* Set the periodic element of this atom specified by its periodic symbol
* (This setter was needed for Hibernate mapping)
* @param symbol the periodic symbol of the element
* @throws MonosaccharideException in case the symbol parameter is not a valid periodic symbol
*/
public void setElementSymbol(String symbol) throws ResourcesDbException {
this.setElement(Periodic.getElementBySymbol(symbol));
}
/**
* Get the atom's charge (Double Object)
* @return the charge
*/
public Double getCharge() {
return this.charge;
}
/**
* Get the atom's charge (simple double value)
* @return the charge
*/
public double getChargeValue() {
if(this.getCharge() == null) {
return(0.0);
}
return(this.getCharge().doubleValue());
}
/**
* Set the atom's charge using a Double Object
* @param charge the charge to set
*/
public void setCharge(Double charge) {
this.charge = charge;
}
/**
* Set the atom's charge using a simple double value
* @param charge the charge to set
*/
public void setCharge(double charge) {
this.charge = new Double(charge);
}
/**
* Get the list of connections to other atoms
* @return the connections
*/
public List<AtomConnection> getConnections() {
return this.connectionList;
}
/**
* Set the list of connections to other atoms
* @param connections the connections to set
*/
public void setConnections(List<AtomConnection> connections) {
this.connectionList = connections;
}
/**
* Add a connection to another atom
* @param to the atom to which this atom is connected
* @param bo the bond order of the connection
*/
public void addConnection(Atom to, double bo) {
if(!this.hasConnection(to)) {
this.addConnection(new AtomConnection(this, to, bo));
}
if(!to.hasConnection(this)) {
to.addConnection(this, bo);
}
}
/**
* Add a connection to another atom
* @param conect the connection object
*/
public void addConnection(AtomConnection conect) {
this.getConnections().add(conect);
}
/**
* The first connection to a specified atom is removed from the connections list.
* @param to the Atom the connection to which shall be removed
* @return true, if such a connection was present
*/
public boolean removeConnection(Atom to) {
for(AtomConnection ac : this.getConnections()) {
if(ac.getToAtom() == to) {
this.getConnections().remove(ac);
return(true);
}
}
return(false);
}
public boolean hasConnection(Atom to) {
for(AtomConnection ac : this.getConnections()) {
if(ac.getToAtom().equals(to)) {
return true;
}
}
return false;
}
/**
* Get a clone of the connections list.
* @return a clone of the connections list
*/
public List<AtomConnection> getConnectionsClone() {
List<AtomConnection> retList = new ArrayList<AtomConnection>();
for(AtomConnection ac : this.getConnections()) {
retList.add(ac.clone());
}
return(retList);
}
/**
* Get the isotope of this atom
* @return the isotope
*/
public Isotope getIsotope() {
return this.isotope;
}
/**
* Set the isotope for this atom
* @param iso the isotope to set
*/
public void setIsotope(Isotope iso) {
this.isotope = iso;
}
/**
* Get the database Id of this atom
* @return the database Id
*/
public int getDbId() {
return this.dbId;
}
/**
* Set the database Id of this atom
* @param dbId the database Id to set
*/
public void setDbId(int dbId) {
this.dbId = dbId;
}
/**
* Get the value of the flag that marks atoms, which are deleted in a linkage
* (e.g. atoms of a basetype OH-group that is replaced by a DEOXY-linked substituent)
* @return the deletedInLinkage flag
*/
public boolean isDeletedInLinkage() {
return this.deletedInLinkage;
}
/**
* Set the deletedInLinkage flag
* @param flag
*/
public void setDeletedInLinkage(boolean flag) {
this.deletedInLinkage = flag;
}
/**
* Get the X coordinate of this atom
* @return the X coordinate
*/
public Double getX() {
return this.x;
}
/**
* Set the X coordinate of this atom
* @param xD the X cooridinate to set
*/
public void setX(Double xD) {
this.x = xD;
}
/**
* Get the Y coordinate of this atom
* @return the Y coordinate
*/
public Double getY() {
return this.y;
}
/**
* Set the Y coordinate of this atom
* @param yD the Y cooridinate to set
*/
public void setY(Double yD) {
this.y = yD;
}
/**
* Get the Z coordinate of this atom
* @return the Z coordinate
*/
public Double getZ() {
return this.z;
}
/**
* Set the Z coordinate of this atom
* @param zD the Z cooridinate to set
*/
public void setZ(Double zD) {
this.z = zD;
}
/**
* Set the coordinates of this atom
* @param xD the X cooridinate to set
* @param yD the Y cooridinate to set
* @param zD the Z cooridinate to set
*/
public void setCoordinates(Double xD, Double yD, Double zD) {
this.setX(xD);
this.setY(yD);
this.setZ(zD);
}
//*****************************************************************************
//*** connection related methods: *********************************************
//*****************************************************************************
/**
* Get the sum of the bond orders of this atom's connections
* @return the bond order sum
*/
public double getBondSum() {
double bs = 0;
for(AtomConnection ac : this.getConnections()) {
bs += ac.getBondOrder().doubleValue();
}
return(bs);
}
public int countBonds() {
if(this.getConnections() == null) {
return 0;
}
return this.getConnections().size();
}
public int countBondsByBondorder(double bo) {
int count = 0;
if(this.getConnections() != null) {
for(AtomConnection con : this.getConnections()) {
if(con.getBondOrder() == bo) {
count ++;
}
}
}
return count;
}
public int countSingleBonds() {
return this.countBondsByBondorder(1.0);
}
public int countDoubleBonds() {
return this.countBondsByBondorder(2.0);
}
public int countAromaticBonds() {
return this.countBondsByBondorder(1.5);
}
public int countTripleBonds() {
return this.countBondsByBondorder(3.0);
}
public Atom getConnectedAtom(String elemSymbol, int index) {
if(this.getConnections() != null) {
int count = 0;
for(AtomConnection acon : this.getConnections()) {
Atom toAtom = acon.getToAtom();
if(toAtom.equals(this)) {
toAtom = acon.getFromAtom();
}
if(toAtom.getElementSymbol() != null && toAtom.getElementSymbol().equals(elemSymbol)) {
count ++;
if(count == index) {
return toAtom;
}
}
}
}
return null;
}
public int countConnectedAtoms(String elemSymbol) {
int count = 0;
if(this.getConnections() != null) {
for(AtomConnection acon : this.getConnections()) {
Atom toAtom = acon.getToAtom();
if(toAtom.equals(this)) {
toAtom = acon.getFromAtom();
}
if(toAtom.getElementSymbol() != null && toAtom.getElementSymbol().equals(elemSymbol)) {
count ++;
}
}
}
return count;
}
//*****************************************************************************
//*** xml parsing methods: ****************************************************
//*****************************************************************************
public static Atom parseXmlAtomTag(org.jdom.Element atomtag) throws ResourcesDbException {
Atom a = null;
if(atomtag.getName().equalsIgnoreCase("atom")) {
a = new Atom();
a.setId(Integer.parseInt(atomtag.getAttributeValue("id")));
a.setName(atomtag.getAttributeValue("name"));
a.setElement(Periodic.getElementBySymbol(atomtag.getAttributeValue("element")));
a.setX(NumberUtils.parseDoubleStr(atomtag.getAttributeValue("x"), null));
a.setY(NumberUtils.parseDoubleStr(atomtag.getAttributeValue("y"), null));
a.setZ(NumberUtils.parseDoubleStr(atomtag.getAttributeValue("z"), null));
}
return(a);
}
//*****************************************************************************
//*** other methods: **********************************************************
//*****************************************************************************
/**
* Initialize the atom properties
*/
public void init() {
this.setId(0);
this.setDbId(0);
this.setName(null);
this.setElement(null);
this.setIsotope(null);
this.setCharge(null);
this.setConnections(new ArrayList<AtomConnection>());
}
/**
* Check, if this atom equals another atom
* @param o another atom
* @return true, if the name, element and isotope of o equal those of this atom
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object o) {
if(o instanceof Atom) {
Atom a = (Atom) o;
if((a.getName() == null && this.getName() == null) || (a.getName() != null && a.getName().equals(this.getName()))) {
if((a.getElement() == null && this.getElement() == null) || (a.getElement() != null && a.getElement().equals(this.getElement()))) {
if((a.getIsotope() == null && this.getIsotope() == null) || (a.getIsotope() != null && a.getIsotope().equals(this.getIsotope()))) {
return(true);
}
}
}
}
return(false);
}
public String toString() {
String outStr;
outStr = "Atom [Id: " + this.getId() + " Element: " + this.getElement().getSymbol() + " Name: " + this.getName() + " Charge: " + this.getCharge();
if(this.isDeletedInLinkage()) {
outStr += " (deleted)";
}
outStr += "]";
return(outStr);
}
public Atom clone() {
Atom a = new Atom(this.getElement());
a.setName(this.getName());
a.setIsotope(this.getIsotope());
a.setCharge(this.getCharge());
a.setConnections(this.getConnectionsClone());
a.setTemplate(this.getTemplate());
a.setMol2Type(this.getMol2Type());
a.setX(this.getX());
a.setY(this.getY());
a.setZ(this.getZ());
return(a);
}
/**
* Remove an atom from a list.
* The given atom is removed from the list. Connections from other atoms to this one are removed as well.
* @param atomList a list of atoms
* @param a the atom to be removed
* @param removeHydrogens flag to indicate if hydrogens that are attached to the removed atom are to be removed as well
*/
public static void removeAtomFromList(List<Atom> atomList, Atom a, boolean removeHydrogens) {
Atom aClone = null;
for(Atom listAtom : atomList) {
if(listAtom.equals(a)) {
aClone = listAtom;
break;
}
}
atomList.remove(aClone);
for(AtomConnection con : aClone.getConnections()) {
Atom toAtom = null;
if(con.getToAtom().equals(aClone)) {
toAtom = con.getFromAtom();
} else {
toAtom = con.getToAtom();
}
if(removeHydrogens) { //*** remove attached hydrogens ***
if(toAtom.getElementSymbol().equals("H")) {
atomList.remove(con.getToAtom());
continue;
}
}
//*** remove back-connection to removed atom: ***
ArrayList<AtomConnection> removeCons = new ArrayList<AtomConnection>();
for(AtomConnection backCon : toAtom.getConnections()) {
if(backCon.getToAtom().equals(aClone)) {
removeCons.add(backCon);
//toAtom.getConnections().remove(backCon);
}
}
for(AtomConnection remCon : removeCons) {
toAtom.getConnections().remove(remCon);
}
}
}
public static void printAtoms(List<Atom> atomList) {
for(Atom a : atomList) {
System.out.println(a.toString());
for(AtomConnection con : a.getConnections()) {
System.out.println(" " + con.toString());
}
}
}
}