
org.biojava.nbio.structure.HetatomImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of biojava-structure Show documentation
Show all versions of biojava-structure Show documentation
The protein structure modules of BioJava.
/*
* BioJava development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public Licence. This should
* be distributed with the code. If you do not have a copy,
* see:
*
* http://www.gnu.org/copyleft/lesser.html
*
* Copyright for this code is held jointly by the individual
* authors. These should be listed in @author doc comments.
*
* For more information on the BioJava project and its aims,
* or to join the biojava-l mailing list, visit the home page
* at:
*
* http://www.biojava.org/
*
* Created on 05.03.2004
* @author Andreas Prlic
*
*/
package org.biojava.nbio.structure;
import org.biojava.nbio.structure.io.GroupToSDF;
import org.biojava.nbio.structure.io.mmcif.ChemCompGroupFactory;
import org.biojava.nbio.structure.io.mmcif.model.ChemComp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.*;
/**
*
* Generic Implementation of a Group interface.
* AminoAcidImpl and NucleotideImpl are closely related classes.
* @see AminoAcidImpl
* @see NucleotideImpl
* @author Andreas Prlic
* @author Horvath Tamas
* @version %I% %G%
* @since 1.4
*/
public class HetatomImpl implements Group,Serializable {
private static final Logger logger = LoggerFactory.getLogger(HetatomImpl.class);
private static final long serialVersionUID = 4491470432023820382L;
/**
* The GroupType is HETATM
*/
public static final GroupType type = GroupType.HETATM ;
private Map properties ;
private long id;
/** stores if 3d coordinates are available. */
protected boolean pdb_flag ;
/** 3 letter name of amino acid in pdb file. */
protected String pdb_name ;
protected ResidueNumber residueNumber;
protected List atoms ;
private Chain parent;
/**
* Behaviors for how to balance memory vs. performance.
* @author Andreas Prlic
*/
public static enum PerformanceBehavior {
/** use a built-in HashMap for faster access to memory, at the price of more memory consumption */
BETTER_PERFORMANCE_MORE_MEMORY,
/** Try to minimize memory consumption, at the price of slower speed when accessing atoms by name */
LESS_MEMORY_SLOWER_PERFORMANCE
}
public static PerformanceBehavior performanceBehavior=PerformanceBehavior.LESS_MEMORY_SLOWER_PERFORMANCE;
private Map atomNameLookup;
private ChemComp chemComp ;
private List altLocs;
/**
* Construct a Hetatom instance.
*/
public HetatomImpl() {
super();
pdb_flag = false;
pdb_name = null ;
residueNumber = null;
atoms = new ArrayList();
properties = new HashMap();
parent = null;
chemComp = null;
altLocs = null;
if ( performanceBehavior == PerformanceBehavior.BETTER_PERFORMANCE_MORE_MEMORY)
atomNameLookup = new HashMap();
else
atomNameLookup = null;
}
/**
* returns true or false, depending if this group has 3D coordinates or not.
* @return true if Group has 3D coordinates
*/
@Override
public boolean has3D() {
return pdb_flag;
}
/** flag if group has 3D data.
*
* @param flag true to set flag that this Group has 3D coordinates
*/
@Override
public void setPDBFlag(boolean flag){
pdb_flag = flag ;
}
/** Set three character name of Group .
*
* @param s a String specifying the PDBName value
* @see #getPDBName
*/
@Override
public void setPDBName(String s) {
// hetatoms can have pdb_name length < 3. e.g. CU (see 1a4a position 1200 )
//if (s.length() != 3) {
//throw new PDBParseException("amino acid name is not of length 3!");
//}
if (s != null && s.equals("?")) logger.info("invalid pdbname: ?");
pdb_name =s ;
}
/**
* Returns the PDBName.
*
* @return a String representing the PDBName value
* @see #setPDBName
*/
@Override
public String getPDBName() { return pdb_name;}
/**
* {@inheritDoc}
*/
@Override
public void addAtom(Atom atom){
atom.setGroup(this);
atoms.add(atom);
if (atom.getCoords() != null){
// we have got coordinates!
setPDBFlag(true);
}
if (atomNameLookup != null){
Atom existingAtom = atomNameLookup.put(atom.getName(), atom);
// if an atom with same name is added to the group that has to be some kind of problem,
// we need to warn properly
if (existingAtom != null) {
String altLocStr = "";
char altLoc = atom.getAltLoc();
if (altLoc != ' ') altLocStr = "(alt loc '" + altLoc + "')";
logger.warn("An atom with name " + atom.getName() + " " + altLocStr + " is already present in group: " + this.toString() + ". The atom with serial " + atom.getPDBserial() + " will be ignored in look-ups.");
}
}
};
/** remove all atoms
*
*/
@Override
public void clearAtoms() {
atoms.clear();
setPDBFlag(false);
if ( atomNameLookup != null)
atomNameLookup.clear();
}
/**
* {@inheritDoc}
*/
@Override
public int size(){ return atoms.size(); }
/**
* {@inheritDoc}
*/
@Override
public List getAtoms(){
return atoms ;
}
/**
* {@inheritDoc}
*/
@Override
public void setAtoms(List atoms) {
// important we are resetting atoms to a new list, we need to reset the lookup too!
if ( atomNameLookup != null)
atomNameLookup.clear();
for (Atom a: atoms){
a.setGroup(this);
if ( atomNameLookup != null)
atomNameLookup.put(a.getName(),a);
}
this.atoms = atoms;
if (!atoms.isEmpty()) {
pdb_flag = true;
}
}
/**
* {@inheritDoc}
*/
@Override
public Atom getAtom(String name) {
if ( atomNameLookup != null)
return atomNameLookup.get(name);
else {
/** This is the performance penalty we pay for NOT using the atomnameLookup in PerformanceBehaviour.LESS_MEMORY_SLOWER_PERFORMANCE
*/
for (Atom a : atoms) {
if (a.getName().equals(name)) {
return a;
}
}
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public Atom getAtom(int position) {
if ((position < 0)|| ( position >= atoms.size())) {
//throw new StructureException("No atom found at position "+position);
return null;
}
return atoms.get(position);
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasAtom(String fullName) {
if ( atomNameLookup != null) {
Atom a = atomNameLookup.get(fullName.trim());
return a != null;
} else {
/** This is the performance penalty we pay for NOT using the atomnameLookup in PerformanceBehaviour.LESS_MEMORY_SLOWER_PERFORMANCE
*/
for (Atom a : atoms) {
if (a.getName().equals(fullName)) {
return true;
}
}
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public GroupType getType(){ return type;}
@Override
public String toString(){
String str = "Hetatom "+ residueNumber + " " + pdb_name + " "+ pdb_flag;
if (pdb_flag) {
str = str + " atoms: "+atoms.size();
}
if ( altLocs != null)
str += " has altLocs :" + altLocs.size();
return str ;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasAminoAtoms(){
// if this method call is performed too often, it should become a
// private method and provide a flag for Group object ...
return hasAtom(StructureTools.CA_ATOM_NAME) &&
hasAtom(StructureTools.C_ATOM_NAME) &&
hasAtom(StructureTools.N_ATOM_NAME) &&
hasAtom(StructureTools.O_ATOM_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public void setProperties(Map props) {
properties = props ;
}
/** return properties.
*
* @return a HashMap object representing the properties value
* @see #setProperties
*/
@Override
public Map getProperties() {
return properties ;
}
/** set a single property .
*
* @see #getProperties
* @see #getProperty
*/
@Override
public void setProperty(String key, Object value){
properties.put(key,value);
}
/** get a single property .
* @param key a String
* @return an Object
* @see #setProperty
* @see #setProperties
*/
@Override
public Object getProperty(String key){
return properties.get(key);
}
/** return an AtomIterator.
*
* @return an Iterator object
*/
@Override
public Iterator iterator() {
return new AtomIterator(this);
}
/** returns and identical copy of this Group object .
* @return and identical copy of this Group object
*/
@Override
public Object clone() {
HetatomImpl n = new HetatomImpl();
n.setPDBFlag(has3D());
n.setResidueNumber(residueNumber);
n.setPDBName(getPDBName());
// copy the atoms
for (Atom atom1 : atoms) {
Atom atom = (Atom) atom1.clone();
n.addAtom(atom);
atom.setGroup(n);
}
// copying the alt loc groups if present, otherwise they stay null
if (altLocs!=null) {
for (Group altLocGroup:this.altLocs) {
Group nAltLocGroup = (Group)altLocGroup.clone();
n.addAltLoc(nAltLocGroup);
}
}
return n;
}
/** the Hibernate database ID
*
* @return the id
*/
public long getId() {
return id;
}
/** the Hibernate database ID
*
* @param id the hibernate id
*/
public void setId(long id) {
this.id = id;
}
@Override
public ChemComp getChemComp() {
if ( chemComp == null ) {
chemComp = ChemCompGroupFactory.getChemComp(pdb_name);
if (chemComp == null) logger.info("getChemComp: " + pdb_name);
}
return chemComp;
}
@Override
public void setChemComp(ChemComp cc) {
chemComp = cc;
}
/**
* {@inheritDoc}
*/
@Override
public void setChain(Chain chain) {
this.parent = chain;
//TODO: setChain(), getChainId() and ResidueNumber.set/getChainId() are
//duplicating functionality at present and could give different values.
if (residueNumber != null) {
residueNumber.setChainId(chain.getChainID());
}
}
/**
* {@inheritDoc}
*/
@Override
public Chain getChain() {
return parent;
}
/**
* {@inheritDoc}
*/
@Override
public String getChainId() {
if (parent == null) {
return "";
}
return parent.getChainID();
}
/**
* {@inheritDoc}
*/
@Override
public ResidueNumber getResidueNumber() {
return residueNumber;
}
@Override
public void setResidueNumber(ResidueNumber residueNumber) {
this.residueNumber = residueNumber;
}
@Override
public void setResidueNumber(String chainId, Integer resNum, Character iCode) {
this.residueNumber = new ResidueNumber(chainId, resNum, iCode);
}
@Override
public boolean hasAltLoc() {
if ( altLocs == null)
return false;
return !altLocs.isEmpty();
}
@Override
public List getAltLocs() {
if ( altLocs == null)
return new ArrayList();
return altLocs;
}
@Override
public Group getAltLocGroup(Character altLoc) {
Atom a = getAtom(0);
if ( a == null) {
return null;
}
// maybe the alt loc group in question is myself
if (a.getAltLoc().equals(altLoc)) {
return this;
}
if (altLocs == null || altLocs.isEmpty())
return null;
for (Group group : altLocs) {
if (group.getAtoms().isEmpty())
continue;
// determine this group's alt-loc character code by looking
// at its first atom's alt-loc character
Atom b = group.getAtom(0);
if ( b == null)
continue;
if (b.getAltLoc().equals(altLoc)) {
return group;
}
}
return null;
}
@Override
public void addAltLoc(Group group) {
if ( altLocs == null) {
altLocs = new ArrayList();
}
altLocs.add(group);
}
@Override
public boolean isWater() {
return GroupType.WATERNAMES.contains(pdb_name);
}
/** attempts to reduce the memory imprint of this group by trimming
* all internal Collection objects to the required size.
*
*/
@Override
public void trimToSize(){
if ( atoms instanceof ArrayList>) {
ArrayList myatoms = (ArrayList) atoms;
myatoms.trimToSize();
}
if ( altLocs instanceof ArrayList>){
ArrayList myAltLocs = (ArrayList) altLocs;
myAltLocs.trimToSize();
}
if ( hasAltLoc()) {
for (Group alt : getAltLocs()){
alt.trimToSize();
}
}
// now let's fit the hashmaps to size
properties = new HashMap(properties);
if ( atomNameLookup != null)
atomNameLookup = new HashMap(atomNameLookup);
}
@Override
public String toSDF() {
// Function to return the SDF of a given strucutre
GroupToSDF gts = new GroupToSDF();
return gts.getText(this);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy