org.biojava.nbio.structure.StructureImpl 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 26.04.2004
* @author Andreas Prlic
*
*/
package org.biojava.nbio.structure;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import org.biojava.nbio.structure.io.FileConvert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of a PDB Structure. This class
* provides the data contained in a PDB file.
* to get structure objects from different sources
* see io package.
*
* @author Andreas Prlic
* @author Jules Jacobsen
* @since 1.4
* @version %I% %G%
*/
public class StructureImpl implements Structure {
private static final long serialVersionUID = -8344837138032851348L;
private static final Logger logger = LoggerFactory.getLogger(StructureImpl.class);
private PdbId pdbId ;
private List models;
private List entityInfos;
private List dbrefs;
private List ssbonds;
private List sites;
private String name ;
private StructureIdentifier structureIdentifier;
private PDBHeader pdbHeader;
private boolean biologicalAssembly;
/**
* Constructs a StructureImpl object.
*/
public StructureImpl() {
super();
models = new ArrayList<>();
name = "";
entityInfos = new ArrayList<>();
dbrefs = new ArrayList<>();
pdbHeader = new PDBHeader();
ssbonds = new ArrayList<>();
sites = new ArrayList<>();
}
/**
* Construct a Structure object that only contains a single group
*
* @param g group object
*/
public StructureImpl(Group g){
this();
Chain c = new ChainImpl();
c.addGroup(g);
addChain(c);
}
/**
* Construct a Structure object that contains a particular chain
*
* @param c chain
*/
public StructureImpl(Chain c){
this();
addChain(c);
}
/**
* Returns an identical copy of this structure .
* @return an identical Structure object
*/
@Override
public Structure clone() {
// Note: structures are also cloned in SubstructureIdentifier.reduce().
// Changes might need to be made there as well
Structure n = new StructureImpl();
// go through whole substructure and clone ...
// copy structure data
n.setPdbId(getPdbId());
n.setName(getName());
//TODO the header data is not being deep-copied, that's a minor issue since it is just some static metadata, but we should recheck this if needed - JD 2014-12-11
n.setPDBHeader(pdbHeader);
n.setDBRefs(this.getDBRefs());
n.setSites(getSites());
// go through each chain and clone chain
for (int i=0;i cloned_model = new ArrayList<>();
for (int j=0;j newEntityInfoList = new ArrayList<>();
for (EntityInfo entityInfo : this.entityInfos) {
EntityInfo newEntityInfo = new EntityInfo(entityInfo); // this sets everything but the chains
for (String asymId:entityInfo.getChainIds()) {
for (int modelNr=0;modelNr models.size())
throw new StructureException(" no model nr " + modelnr +
" in this structure. (contains "+models.size()+")");
// first we need to gather all groups with the author id chainName: polymers, non-polymers and waters
Chain polyChain = getPolyChainByPDB(chainName, modelnr);
if(polyChain != null) {
List groups = new ArrayList<>();
groups.addAll(polyChain.getAtomGroups());
// there can be more than one non-poly chain for a given author id
for (Chain chain: getNonPolyChainsByPDB(chainName, modelnr)) {
groups.addAll(chain.getAtomGroups());
}
Chain water = getWaterChainByPDB(chainName, modelnr);
if (water!=null)
groups.addAll(water.getAtomGroups());
// now iterate over all groups
// in order to find the amino acid that has this pdbRenum.
for (Group g : groups) {
String rnum = g.getResidueNumber().toString();
//System.out.println(g + " >" + rnum + "< >" + pdbResnum + "<");
// we only mutate amino acids
// and ignore hetatoms and nucleotides in this case
if (rnum.equals(pdbResnum)) {
return g;
}
}
}
throw new StructureException("could not find group " + pdbResnum +
" in chain " + chainName);
}
/** {@inheritDoc} */
@Override
public Group findGroup(String chainName, String pdbResnum) throws StructureException
{
return findGroup(chainName, pdbResnum, 0);
}
/** {@inheritDoc} */
@Override
public void setName(String nam) { name = nam; }
/** {@inheritDoc} */
@Override
public String getName() { return name; }
/**
* @return The StructureIdentifier used to create this structure
*/
@Override
public StructureIdentifier getStructureIdentifier() {
return structureIdentifier;
}
/**
* @param structureIdentifier the structureIdentifier corresponding to this structure
*/
@Override
public void setStructureIdentifier(StructureIdentifier structureIdentifier) {
this.structureIdentifier = structureIdentifier;
}
/** {@inheritDoc} */
@Override
public void addChain(Chain chain) {
int modelnr = 0 ;
addChain(chain,modelnr);
}
/** {@inheritDoc} */
@Override
public void addChain(Chain chain, int modelnr) {
// if model has not been initialized, init it!
chain.setStructure(this);
if (models.isEmpty()) {
Model model = new Model();
List modelChains = new ArrayList<>() ;
modelChains.add(chain);
model.setChains(modelChains);
models.add(model);
} else {
Model model = models.get(modelnr);
model.addChain(chain);
}
}
/** {@inheritDoc} */
@Override
public Chain getChainByIndex(int number) {
int modelnr = 0 ;
return getChainByIndex(modelnr,number);
}
/** {@inheritDoc} */
@Override
public Chain getChainByIndex(int modelnr,int number) {
Model model = models.get(modelnr);
return model.getChains().get(number);
}
/** {@inheritDoc} */
@Override
public void addModel(List modelChains){
for (Chain c: modelChains){
c.setStructure(this);
}
Model model = new Model();
model.setChains(modelChains);
models.add(model);
}
/** {@inheritDoc} */
@Override
public void setChains(List chains){
setModel(0,chains);
}
/** {@inheritDoc} */
@Override
public void setModel(int position, List modelChains){
if (modelChains == null)
throw new IllegalArgumentException("trying to set model to null!");
for (Chain c: modelChains)
c.setStructure(this);
//System.out.println("model size:" + models.size());
Model model = new Model();
model.setChains(modelChains);
if (models.isEmpty()){
models.add(model);
} else {
models.set(position, model);
}
}
/** String representation.
*
*/
@Override
public String toString(){
String newline = System.getProperty("line.separator");
StringBuilder str = new StringBuilder();
str.append("structure ");
str.append(name);
str.append(" ");
str.append(pdbId);
str.append(" ");
if ( nrModels()>1 ){
str.append( " models: ");
str.append(nrModels());
str.append(newline) ;
}
str.append(pdbHeader);
str.append(newline) ;
for (int i=0;i1 ) {
str.append(" model[");
str.append(i);
str.append("]:");
str.append(newline);
}
str.append(" chains:");
str.append(newline);
for (int j=0;j agr = cha.getAtomGroups(GroupType.AMINOACID);
List hgr = cha.getAtomGroups(GroupType.HETATM);
List ngr = cha.getAtomGroups(GroupType.NUCLEOTIDE);
str.append("chain ")
.append(j).append(": asymId:")
.append(cha.getId())
.append(" authId:")
.append(cha.getName()).append(" ");
if ( cha.getEntityInfo() != null){
EntityInfo comp = cha.getEntityInfo();
String molName = comp.getDescription();
if ( molName != null){
str.append(molName);
}
String type = comp.getType().toString();
str.append(" (")
.append(type)
.append(")");
}
str.append(newline);
str.append(" length SEQRES: ").append(cha.getSeqResLength());
str.append(" length ATOM: ").append(cha.getAtomLength());
str.append(" aminos: ").append(agr.size());
str.append(" hetatms: ").append(hgr.size());
str.append(" nucleotides: ").append(ngr.size()).append(newline);
}
}
str.append("DBRefs: ").append(dbrefs.size()).append(newline);
for (DBRef dbref: dbrefs){
str.append(dbref.toPDB()).append(newline);
}
str.append("Molecules: ").append(newline);
for (EntityInfo mol : entityInfos) {
str.append(mol).append(newline);
}
return str.toString() ;
}
@Override
public int size() {
int modelnr = 0 ;
if (!models.isEmpty()) {
return models.get(modelnr).getPolyChains().size();
}
else {
return 0 ;
}
}
/** return number of chains of model.
*
*/
@Override
public int size(int modelnr) { return models.get(modelnr).size(); }
// some NMR stuff :
/** return number of models. */
@Override
public int nrModels() {
return models.size() ;
}
/**
* Whether this Structure is a crystallographic structure or not.
* It will first check the experimental technique and if not present it will try
* to guess from the presence of a space group and sensible cell parameters
*
* @return true if crystallographic, false otherwise
*/
@Override
public boolean isCrystallographic() {
if (pdbHeader.getExperimentalTechniques()!=null) {
return ExperimentalTechnique.isCrystallographic(pdbHeader.getExperimentalTechniques());
} else {
// no experimental technique known, we try to guess...
if (pdbHeader.getCrystallographicInfo().getSpaceGroup()!=null) {
// space group defined but no crystal cell: incomplete info, return false
return pdbHeader.getCrystallographicInfo().getCrystalCell() != null &&
pdbHeader.getCrystallographicInfo().getCrystalCell().isCellReasonable();
}
}
return false;
}
/**
* Whether this Structure is a NMR structure or not.
* It will first check the experimental technique and if not present it will try
* to guess from the presence of more than 1 model and from b-factors being 0 in first chain of first model
* @return true if NMR, false otherwise
*/
@Override
public boolean isNmr() {
// old implementation was:
//return nmrflag;
if (pdbHeader.getExperimentalTechniques()!=null) {
return ExperimentalTechnique.isNmr(pdbHeader.getExperimentalTechniques());
} else {
// no experimental technique known, we try to guess...
if (nrModels()>1) {
if (pdbHeader.getCrystallographicInfo().getSpaceGroup()!=null) {
// multimodel, sg defined, but missing cell: must be NMR
if (pdbHeader.getCrystallographicInfo().getCrystalCell()==null)
return true;
// multi-model, sg defined and cell unreasonable: must be NMR
if (!pdbHeader.getCrystallographicInfo().getCrystalCell().isCellReasonable())
return true;
} else {
// multi-model and missing space group: must be NMR
return true;
}
}
}
return false;
}
/** {@inheritDoc} */
@Override
public List getChains(int modelIdx){
return getModel(modelIdx);
}
/** {@inheritDoc} */
@Override
public List getChains(){
if (models.size()==0) {
return new ArrayList<>(0);
}
return getChains(0);
}
@Override
public List getPolyChains() {
if (models.size()==0) {
return new ArrayList<>(0);
}
return getPolyChains(0);
}
@Override
public List getPolyChains(int modelIdx) {
return models.get(modelIdx).getPolyChains();
}
@Override
public List getNonPolyChains() {
if (models.size()==0) {
return new ArrayList<>(0);
}
return getNonPolyChains(0);
}
@Override
public List getNonPolyChains(int modelIdx) {
return models.get(modelIdx).getNonPolyChains();
}
@Override
public List getWaterChains() {
if (models.size()==0) {
return new ArrayList<>(0);
}
return getWaterChains(0);
}
@Override
public List getWaterChains(int modelIdx) {
return models.get(modelIdx).getWaterChains();
}
/** {@inheritDoc} */
@Override
public void setChains(int modelnr, List chains){
for (Chain c: chains){
c.setStructure(this);
}
if (models.size()>modelnr) {
models.remove(modelnr);
}
Model model = new Model();
model.setChains(chains);
models.add(modelnr, model);
}
/** Retrieve all Chains belonging to a model .
*
* @param modelnr an int
* @return a List object
*/
@Override
public List getModel(int modelnr) {
return models.get(modelnr).getChains();
}
/** {@inheritDoc} */
@Override
public Chain getChain(String asymId, int modelnr) {
List chains = getChains(modelnr);
for (Chain c : chains) {
if (c.getId().equals(asymId)) {
return c;
}
}
return null;
}
/** {@inheritDoc} */
@Override
public Chain getChain(String asymId) {
return getChain(asymId,0);
}
@Override
public Chain getPolyChain(String asymId) {
return getPolyChain(asymId, 0);
}
@Override
public Chain getPolyChain(String asymId, int modelIdx) {
Model model = models.get(modelIdx);
if (model==null) {
return null;
}
List polyChains = model.getPolyChains();
for (Chain c : polyChains){
if (c.getId().equals(asymId))
return c;
}
return null;
}
@Override
public Chain getNonPolyChain(String asymId) {
return getNonPolyChain(asymId, 0);
}
@Override
public Chain getNonPolyChain(String asymId, int modelIdx) {
Model model = models.get(modelIdx);
if (model==null) {
return null;
}
List nonpolyChains = model.getNonPolyChains();
for (Chain c : nonpolyChains){
if (c.getId().equals(asymId))
return c;
}
return null;
}
@Override
public Chain getPolyChainByPDB(String authId) {
return getPolyChainByPDB(authId, 0);
}
@Override
public Chain getPolyChainByPDB(String authId, int modelIdx) {
Model model = models.get(modelIdx);
if (model==null) {
return null;
}
List polyChains = model.getPolyChains();
for (Chain c : polyChains){
if (c.getName().equals(authId))
return c;
}
return null;
}
@Override
public List getNonPolyChainsByPDB(String authId) {
return getNonPolyChainsByPDB(authId, 0);
}
@Override
public List getNonPolyChainsByPDB(String authId, int modelIdx) {
List chains = new ArrayList<>();
Model model = models.get(modelIdx);
if (model==null) {
return chains;
}
List nonpolyChains = model.getNonPolyChains();
for (Chain c : nonpolyChains){
if (c.getName().equals(authId))
chains.add(c);
}
return chains;
}
@Override
public Chain getWaterChain(String asymId) {
return getWaterChain(asymId, 0);
}
@Override
public Chain getWaterChain(String asymId, int modelIdx) {
Model model = models.get(modelIdx);
if (model==null) {
return null;
}
List waterChains = model.getWaterChains();
for (Chain c : waterChains){
if (c.getId().equals(asymId))
return c;
}
return null;
}
@Override
public Chain getWaterChainByPDB(String authId) {
return getWaterChainByPDB(authId, 0);
}
@Override
public Chain getWaterChainByPDB(String authId, int modelIdx) {
Model model = models.get(modelIdx);
if (model==null) {
return null;
}
List waterChains = model.getWaterChains();
for (Chain c : waterChains){
if (c.getName().equals(authId))
return c;
}
return null;
}
/** {@inheritDoc} */
@Override
public String toPDB() {
FileConvert f = new FileConvert(this) ;
return f.toPDB();
}
/** {@inheritDoc} */
@Override
public String toMMCIF() {
FileConvert f = new FileConvert(this);
return f.toMMCIF();
}
/** {@inheritDoc} */
@Override
public boolean hasChain(String authId) {
int modelnr = 0;
List chains = getChains(modelnr);
for (Chain c : chains) {
// we check here with equals because we might want to distinguish between upper and lower case chains!
if (c.getId().equals(authId)) {
return true;
}
}
return false;
}
/** {@inheritDoc} */
@Override
public boolean hasNonPolyChain(String asymId){
int modelnr = 0;
List chains = models.get(modelnr).getNonPolyChains();
for (Chain c : chains) {
// we check here with equals because we might want to distinguish between upper and lower case chains!
if (c.getId().equals(asymId)) {
return true;
}
}
return false;
}
/** {@inheritDoc} */
@Override
public boolean hasPdbChain(String authId) {
int modelnr = 0;
List chains = getChains(modelnr);
for (Chain c : chains) {
// we check here with equals because we might want to distinguish between upper and lower case chains!
if (c.getName().equals(authId)) {
return true;
}
}
return false;
}
/** {@inheritDoc} */
@Override
public void setEntityInfos(List molList){
this.entityInfos = molList;
}
/** {@inheritDoc} */
@Override
public void addEntityInfo(EntityInfo entityInfo) {
this.entityInfos.add(entityInfo);
}
/** {@inheritDoc} */
@Override
public List getEntityInfos() {
return entityInfos;
}
/** {@inheritDoc} */
@Override
public EntityInfo getEntityById(int entityId) {
for (EntityInfo mol : this.entityInfos){
if (mol.getMolId()==entityId){
return mol;
}
}
return null;
}
/** {@inheritDoc} */
@Override
public List getDBRefs() {
return dbrefs;
}
/** {@inheritDoc} */
@Override
public void setDBRefs(List dbrefs) {
if ( dbrefs == null)
throw new IllegalArgumentException("trying to set dbrefs to null!");
for( DBRef ref : dbrefs){
ref.setParent(this);
}
this.dbrefs = dbrefs;
}
/** {@inheritDoc} */
@Override
public PDBHeader getPDBHeader() {
return pdbHeader;
}
/** {@inheritDoc} */
@Override
public void setPDBHeader(PDBHeader pdbHeader){
this.pdbHeader = pdbHeader;
}
/** {@inheritDoc} */
@Override
public List getSSBonds(){
return ssbonds;
}
/** {@inheritDoc} */
@Override
public void setSSBonds(List ssbonds){
this.ssbonds = ssbonds;
}
/**
* Adds a single disulfide Bond to this structure
*
* @param ssbond the SSBond.
*/
@Override
public void addSSBond(Bond ssbond){
ssbonds.add(ssbond);
}
/**
* Return whether or not the entry has an associated journal article
* or publication. The JRNL section is not mandatory and thus may not be
* present.
* @return flag if a JournalArticle could be found.
*/
@Override
public boolean hasJournalArticle() {
return this.pdbHeader.hasJournalArticle();
}
/**
* get the associated publication as defined by the JRNL records in a PDB
* file.
* @return a JournalArticle
*/
@Override
public JournalArticle getJournalArticle() {
return this.pdbHeader.getJournalArticle();
}
/**
* set the associated publication as defined by the JRNL records in a PDB
* file.
* @param journalArticle the article
*/
@Override
public void setJournalArticle(JournalArticle journalArticle) {
this.pdbHeader.setJournalArticle(journalArticle);
}
/**
* @return the sites contained in this structure
*/
@Override
public List getSites() {
return sites;
}
/**
* @param sites the sites to set in the structure
*/
@Override
public void setSites(List sites) {
this.sites = sites;
}
/** Caution: we should probably remove this to avoid confusion. Currently this is always an empty list!
*
* @return a list of Groups listed in the HET records - this will not
* include any waters.
*/
/**
* Sets a flag to indicate if this structure is a biological assembly
* @param biologicalAssembly true if biological assembly, otherwise false
* @since 3.2
*/
@Override
public void setBiologicalAssembly(boolean biologicalAssembly) {
this.biologicalAssembly = biologicalAssembly;
}
/**
* Gets flag that indicates if this structure is a biological assembly
* @return the sites contained in this structure
* @since 3.2
*/
@Override
public boolean isBiologicalAssembly() {
return biologicalAssembly;
}
/**
* Sets crystallographic information for this structure
* @param crystallographicInfo crystallographic information
* @since 3.2
*/
@Override
public void setCrystallographicInfo(PDBCrystallographicInfo crystallographicInfo) {
this.pdbHeader.setCrystallographicInfo(crystallographicInfo);
}
/**
* Gets crystallographic information for this structure
* @return PDBCrystallographicInfo crystallographic information
* @since 3.2
*/
@Override
public PDBCrystallographicInfo getCrystallographicInfo() {
return pdbHeader.getCrystallographicInfo();
}
/** {@inheritDoc} */
@Override
public String getIdentifier() {
//1. StructureIdentifier
if(getStructureIdentifier() != null) {
return getStructureIdentifier().getIdentifier();
}
//2. Name
if(getName() != null) {
return getName();
}
//3. PDBCode + ranges
return toCanonical().getIdentifier();
}
/**
* {@inheritDoc}
* @deprecated use {@link #getPdbId()} to get a {@link PdbId} object or getPdbId().getId() to get a {@link String}
*/
@Deprecated
@Override
public String getPDBCode () {
if(pdbId == null)
return null;
return this.pdbId.getId() ;
}
/** {@inheritDoc}
* @deprecated use {@link #setPDBCode(PdbId)}
* */
@Deprecated
@Override
public void setPDBCode(String pdb_id){
if(pdb_id == null) {
this.pdbId = null;
}else {
pdbId = new PdbId(pdb_id);
}
}
/** {@inheritDoc}
* @since 6.0.0
* */
public PdbId getPdbId() {
return this.pdbId;
}
/** {@inheritDoc}
* @since 6.0.0
* */
public void setPdbId(PdbId pdbId) {
this.pdbId = pdbId;
}
@Override
public void resetModels() {
models = new ArrayList<>();
}
/**
* Creates a SubstructureIdentifier based on the residues in this Structure.
*
* Only the first and last residues of each chain are considered, so chains
* with gaps
* @return A {@link SubstructureIdentifier} with residue ranges constructed from each chain
*/
private SubstructureIdentifier toCanonical() {
StructureIdentifier real = getStructureIdentifier();
if(real != null) {
try {
return real.toCanonical();
} catch (StructureException e) {
// generate fake one if needed
}
}
// No identifier set, so generate based on residues present in the structure
List range = new ArrayList<>();
for (Chain chain : getChains()) {
List groups = chain.getAtomGroups();
ListIterator groupsIt = groups.listIterator();
if(!groupsIt.hasNext()) {
continue; // no groups in chain
}
Group g = groupsIt.next();
ResidueNumber first = g.getResidueNumber();
//TODO Detect missing intermediate residues -sbliven, 2015-01-28
//Already better than previous whole-chain representation
// get last residue
while(groupsIt.hasNext()) {
g = groupsIt.next();
}
ResidueNumber last = g.getResidueNumber();
range.add(new ResidueRange(chain.getName(),first,last));
}
return new SubstructureIdentifier(getPdbId(),range);
}
}