
org.biojava.nbio.structure.align.util.AtomCache Maven / Gradle / Ivy
Show all versions of biojava-structure Show documentation
/*
* 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/
*
*/
package org.biojava.nbio.structure.align.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;
import org.biojava.nbio.core.util.InputStreamProvider;
import org.biojava.nbio.structure.*;
import org.biojava.nbio.structure.align.client.StructureName;
import org.biojava.nbio.structure.cath.CathDatabase;
import org.biojava.nbio.structure.cath.CathDomain;
import org.biojava.nbio.structure.cath.CathFactory;
import org.biojava.nbio.structure.io.BcifFileReader;
import org.biojava.nbio.structure.io.CifFileReader;
import org.biojava.nbio.structure.io.FileParsingParameters;
import org.biojava.nbio.structure.io.LocalPDBDirectory.FetchBehavior;
import org.biojava.nbio.structure.io.LocalPDBDirectory.ObsoleteBehavior;
import org.biojava.nbio.structure.io.PDBFileReader;
import org.biojava.nbio.core.util.FileDownloadUtils;
import org.biojava.nbio.structure.io.StructureFiletype;
import org.biojava.nbio.structure.quaternary.BiologicalAssemblyBuilder;
import org.biojava.nbio.structure.quaternary.BiologicalAssemblyTransformation;
import org.biojava.nbio.structure.scop.ScopDatabase;
import org.biojava.nbio.structure.scop.ScopDescription;
import org.biojava.nbio.structure.scop.ScopDomain;
import org.biojava.nbio.structure.scop.ScopFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A utility class that provides easy access to Structure objects. If you are running a script that is frequently
* re-using the same PDB structures, the AtomCache keeps an in-memory cache of the files for quicker access. The cache
* is a soft-cache, this means it won't cause out of memory exceptions, but garbage collects the data if the Java
* virtual machine needs to free up space. The AtomCache is thread-safe.
*
* @author Andreas Prlic
* @author Spencer Bliven
* @author Peter Rose
* @since 3.0
*/
public class AtomCache {
private static final Logger logger = LoggerFactory.getLogger(AtomCache.class);
/**
* The default output bioassembly style: if true the bioassemblies are multimodel,
* if false the bioassemblies are flat with renamed chains for symmetry-partners.
*/
public static final boolean DEFAULT_BIOASSEMBLY_STYLE = false;
public static final String BIOL_ASSEMBLY_IDENTIFIER = "BIO:";
public static final String CHAIN_NR_SYMBOL = ":";
public static final String CHAIN_SPLIT_SYMBOL = ".";
public static final String UNDERSCORE = "_";
private static final String FILE_SEPARATOR = System.getProperty("file.separator");
protected FileParsingParameters params;
private FetchBehavior fetchBehavior;
private ObsoleteBehavior obsoleteBehavior;
private String cachePath;
// make sure IDs are loaded uniquely
private final Collection currentlyLoading = Collections.synchronizedCollection(new TreeSet<>());
private String path;
private StructureFiletype filetype = StructureFiletype.BCIF;
/**
* Default AtomCache constructor.
*
* Usually stores files in a temp directory, but this can be overriden by setting the PDB_DIR variable at runtime.
*
* @see UserConfiguration#UserConfiguration()
*/
public AtomCache() {
this(new UserConfiguration());
}
/**
* Creates an instance of an AtomCache that is pointed to the a particular path in the file system. It will use the same value for pdbFilePath and cachePath.
*
* @param pdbFilePath
* a directory in the file system to use as a location to cache files.
*/
public AtomCache(String pdbFilePath) {
this(pdbFilePath,pdbFilePath);
}
/**
* Creates an instance of an AtomCache that is pointed to the a particular path in the file system.
*
* @param pdbFilePath
* a directory in the file system to use as a location to cache files.
* @param cachePath
*/
public AtomCache(String pdbFilePath, String cachePath) {
logger.debug("Initialising AtomCache with pdbFilePath={}, cachePath={}", pdbFilePath, cachePath);
if (!pdbFilePath.endsWith(FILE_SEPARATOR)) {
pdbFilePath += FILE_SEPARATOR;
}
// we are caching the binary files that contain the PDBs gzipped
// that is the most memory efficient way of caching...
// set the input stream provider to caching mode
System.setProperty(InputStreamProvider.CACHE_PROPERTY, "true");
setPath(pdbFilePath);
this.cachePath = cachePath;
fetchBehavior = FetchBehavior.DEFAULT;
obsoleteBehavior = ObsoleteBehavior.DEFAULT;
currentlyLoading.clear();
params = new FileParsingParameters();
setFiletype(StructureFiletype.BCIF);
}
/**
* Creates a new AtomCache object based on the provided UserConfiguration.
*
* @param config
* the UserConfiguration to use for this cache.
*/
public AtomCache(UserConfiguration config) {
this(config.getPdbFilePath(), config.getCacheFilePath());
fetchBehavior = config.getFetchBehavior();
obsoleteBehavior = config.getObsoleteBehavior();
filetype = config.getStructureFiletype();
}
/**
* Returns the CA atoms for the provided name. See {@link #getStructure(String)} for supported naming conventions.
*
* This method only works with protein chains. Use {@link #getRepresentativeAtoms(String)}
* for a more general solution.
* @param name
* @return an array of Atoms.
* @throws IOException
* @throws StructureException
*/
public Atom[] getAtoms(String name) throws IOException, StructureException {
return getAtoms(new StructureName(name));
}
public Atom[] getAtoms(StructureIdentifier name) throws IOException, StructureException {
Atom[] atoms;
// System.out.println("loading " + name);
Structure s = getStructure(name);
atoms = StructureTools.getAtomCAArray(s);
/*
* synchronized (cache){ cache.put(name, atoms); }
*/
return atoms;
}
/**
* Returns the representative atoms for the provided name.
* See {@link #getStructure(String)} for supported naming conventions.
*
* @param name
* @return an array of Atoms.
* @throws IOException
* @throws StructureException
*/
public Atom[] getRepresentativeAtoms(String name) throws IOException, StructureException {
return getRepresentativeAtoms(new StructureName(name));
}
public Atom[] getRepresentativeAtoms(StructureIdentifier name) throws IOException, StructureException {
Atom[] atoms;
Structure s = getStructure(name);
atoms = StructureTools.getRepresentativeAtomArray(s);
/*
* synchronized (cache){ cache.put(name, atoms); }
*/
return atoms;
}
/**
* Returns the biological assembly for a given PDB ID and bioAssemblyId, by building the
* assembly from the biounit annotations found in {@link Structure#getPDBHeader()}
*
* Note, the number of available biological unit files
* varies. Many entries don't have a biological assembly specified (e.g. NMR structures), many entries have only one
* biological assembly (bioAssemblyId=1), and some structures have multiple biological assemblies.
*
* @param pdbId
* the PDB ID
* @param bioAssemblyId
* the 1-based index of the biological assembly (0 gets the asymmetric unit)
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
* @return a structure object
* @throws IOException
* @throws StructureException if biassemblyId < 0 or other problems while loading structure
* @since 3.2
*/
public Structure getBiologicalAssembly(String pdbId, int bioAssemblyId, boolean multiModel)
throws StructureException, IOException {
return getBiologicalAssembly(new PdbId(pdbId), bioAssemblyId, multiModel);
}
/**
* Returns the biological assembly for a given PDB ID and bioAssemblyId, by building the
* assembly from the biounit annotations found in {@link Structure#getPDBHeader()}
*
* Note, the number of available biological unit files
* varies. Many entries don't have a biological assembly specified (e.g. NMR structures), many entries have only one
* biological assembly (bioAssemblyId=1), and some structures have multiple biological assemblies.
*
* @param pdbId
* the PDB ID
* @param bioAssemblyId
* the 1-based index of the biological assembly (0 gets the asymmetric unit)
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
* @return a structure object
* @throws IOException
* @throws StructureException if biassemblyId < 0 or other problems while loading structure
* @since 6.0.0
*/
public Structure getBiologicalAssembly(PdbId pdbId, int bioAssemblyId, boolean multiModel)
throws StructureException, IOException {
if (bioAssemblyId < 0) {
throw new StructureException("bioAssemblyID must be nonnegative: " + pdbId + " bioAssemblyId "
+ bioAssemblyId);
}
boolean prevIsParseBioAssembly = getFileParsingParams().isParseBioAssembly();
if (!getFileParsingParams().isParseBioAssembly()) {
getFileParsingParams().setParseBioAssembly(true);
}
Structure asymUnit = getStructureForPdbId(pdbId);
getFileParsingParams().setParseBioAssembly(prevIsParseBioAssembly);
if (asymUnit.getPDBHeader() == null || asymUnit.getPDBHeader().getBioAssemblies() == null) {
logger.info("No bioassembly information found for {}, returning asymmetric unit as biological assembly", pdbId);
return asymUnit;
}
// 0 ... asym unit
if (bioAssemblyId == 0) {
logger.info("Requested biological assembly 0 for PDB id {}, returning asymmetric unit", pdbId);
return asymUnit;
}
// does it exist?
if (!asymUnit.getPDBHeader().getBioAssemblies().containsKey(bioAssemblyId)) {
throw new StructureException("No biological assembly available for biological assembly id " + bioAssemblyId + " of " + pdbId);
}
List transformations =
asymUnit.getPDBHeader().getBioAssemblies().get(bioAssemblyId).getTransforms();
if (transformations == null || transformations.size() == 0) {
throw new StructureException("Could not load transformations to recreate biological assembly id " + bioAssemblyId + " of " + pdbId);
}
BiologicalAssemblyBuilder builder = new BiologicalAssemblyBuilder();
// if we use mmcif or mmtf, then we need to pass useAsymIds=true
boolean useAsymIds = false;
if (filetype == StructureFiletype.CIF || filetype == StructureFiletype.BCIF || filetype == StructureFiletype.MMTF) {
useAsymIds = true;
}
return builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds, multiModel);
}
/**
* Returns the default biological unit (bioassemblyId=1, known in PDB as pdb1.gz). If it is not available,
* the asymmetric unit will be returned, e.g. for NMR structures.
*
* Biological assemblies can also be accessed using
* getStructure("BIO:[pdbId]")
* @param pdbId the PDB id
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
* @return a structure object
* @throws IOException
* @throws StructureException
* @since 4.2
*/
public Structure getBiologicalAssembly(String pdbId, boolean multiModel) throws StructureException, IOException {
boolean prevIsParseBioAssembly = getFileParsingParams().isParseBioAssembly();
if (!getFileParsingParams().isParseBioAssembly()) {
getFileParsingParams().setParseBioAssembly(true);
}
Structure asymUnit = getStructureForPdbId(pdbId);
getFileParsingParams().setParseBioAssembly(prevIsParseBioAssembly);
if (asymUnit.getPDBHeader() == null || asymUnit.getPDBHeader().getBioAssemblies() == null) {
logger.info("No bioassembly information found for {}, returning asymmetric unit as biological assembly", pdbId);
return asymUnit;
}
int bioAssemblyId = 1;
// does it exist?
if (!asymUnit.getPDBHeader().getBioAssemblies().containsKey(bioAssemblyId)) {
return asymUnit;
}
List transformations =
asymUnit.getPDBHeader().getBioAssemblies().get(bioAssemblyId).getTransforms();
if (transformations == null || transformations.size() == 0) {
throw new StructureException("Could not load transformations to recreate biological assembly id " + bioAssemblyId + " of " + pdbId);
}
BiologicalAssemblyBuilder builder = new BiologicalAssemblyBuilder();
// if we use mmcif or mmtf, then we need to pass useAsymIds=true
boolean useAsymIds = false;
if (filetype == StructureFiletype.CIF || filetype == StructureFiletype.BCIF || filetype == StructureFiletype.MMTF) {
useAsymIds = true;
}
return builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds, multiModel);
}
/**
* Returns all biological assemblies for given PDB id.
* @param pdbId
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
* @return
* @throws StructureException
* @throws IOException
* @since 5.0
*/
public List getBiologicalAssemblies(String pdbId, boolean multiModel) throws StructureException, IOException {
List assemblies = new ArrayList<>();
boolean prevIsParseBioAssembly = getFileParsingParams().isParseBioAssembly();
if (!getFileParsingParams().isParseBioAssembly()) {
getFileParsingParams().setParseBioAssembly(true);
}
Structure asymUnit = getStructureForPdbId(pdbId);
getFileParsingParams().setParseBioAssembly(prevIsParseBioAssembly);
if (asymUnit.getPDBHeader() == null || asymUnit.getPDBHeader().getBioAssemblies() == null) {
logger.info("No bioassembly information found for {}, returning asymmetric unit as the only biological assembly", pdbId);
assemblies.add(asymUnit);
return assemblies;
}
for (int bioAssemblyId : asymUnit.getPDBHeader().getBioAssemblies().keySet()) {
List transformations =
asymUnit.getPDBHeader().getBioAssemblies().get(bioAssemblyId).getTransforms();
if (transformations == null || transformations.size() == 0) {
logger.info("Could not load transformations to recreate biological assembly id {} of {}. Assembly " +
"id will be missing in biological assemblies.", bioAssemblyId, pdbId);
continue;
}
BiologicalAssemblyBuilder builder = new BiologicalAssemblyBuilder();
// if we use mmcif or mmtf, then we need to pass useAsymIds=true
boolean useAsymIds = false;
if (filetype == StructureFiletype.CIF || filetype == StructureFiletype.BCIF || filetype == StructureFiletype.MMTF) {
useAsymIds = true;
}
Structure s = builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds, multiModel);
assemblies.add(s);
}
return assemblies;
}
/**
* Returns the path that contains the caching file for utility data, such as domain definitions.
*
* @return
*/
public String getCachePath() {
return cachePath;
}
public FileParsingParameters getFileParsingParams() {
return params;
}
/**
* Get the path that is used to cache PDB files.
*
* @return path to a directory
*/
public String getPath() {
return path;
}
/**
* Request a Structure based on a name.
*
*
* Formal specification for how to specify the name:
*
* name := pdbID
* | pdbID '.' chainID
* | pdbID '.' range
* | scopID
* range := '('? range (',' range)? ')'?
* | chainID
* | chainID '_' resNum '-' resNum
* pdbID := [1-9][a-zA-Z0-9]{3}
* | PDB_[a-zA-Z0-9]{8}
* chainID := [a-zA-Z0-9]
* scopID := 'd' pdbID [a-z_][0-9_]
* resNum := [-+]?[0-9]+[A-Za-z]?
*
*
* Example structures:
* 1TIM #whole structure
* 4HHB.C #single chain
* 4GCR.A_1-83 #one domain, by residue number
* 3AA0.A,B #two chains treated as one structure
* PDB_00001TIM #whole structure (extended format)
* PDB_00004HHB.C #single chain (extended format)
* PDB_00004GCR.A_1-83 #one domain, by residue number (extended format)
* PDB_00003AA0.A,B #two chains treated as one structure (extended format)
* d2bq6a1 #scop domain
*
*
* With the additional set of rules:
*
*
* - If only a PDB code is provided, the whole structure will be return including ligands, but the first model
* only (for NMR).
*
- Chain IDs are case sensitive, PDB ids are not. To specify a particular chain write as: 4hhb.A or 4HHB.A
* - To specify a SCOP domain write a scopId e.g. d2bq6a1.
* - URLs are accepted as well
*
*
* Note that this method should not be used in StructureIdentifier
* implementations to avoid circular calls.
* @param name
* @return a Structure object, or null if name appears improperly formated (eg too short, etc)
* @throws IOException
* The PDB file cannot be cached due to IO errors
* @throws StructureException
* The name appeared valid but did not correspond to a structure. Also thrown by some submethods upon
* errors, eg for poorly formatted subranges.
*/
public Structure getStructure(String name) throws IOException, StructureException {
StructureName structureName = new StructureName(name);
return getStructure(structureName);
}
/**
* Get the structure corresponding to the given {@link StructureIdentifier}.
* Equivalent to calling {@link StructureIdentifier#loadStructure(AtomCache)}
* followed by {@link StructureIdentifier#reduce(Structure)}.
*
*
Note that this method should not be used in StructureIdentifier
* implementations to avoid circular calls.
* @param strucId
* @return
* @throws IOException
* @throws StructureException
*/
public Structure getStructure(StructureIdentifier strucId) throws IOException, StructureException {
Structure s = strucId.loadStructure(this);
Structure r = strucId.reduce(s);
r.setStructureIdentifier(strucId);
return r;
}
/**
* Returns the representation of a {@link ScopDomain} as a BioJava {@link Structure} object.
*
* @param domain
* a SCOP domain
* @return a Structure object
* @throws IOException
* @throws StructureException
*/
public Structure getStructureForDomain(ScopDomain domain) throws IOException, StructureException {
return getStructureForDomain(domain, ScopFactory.getSCOP());
}
/**
* Returns the representation of a {@link ScopDomain} as a BioJava {@link Structure} object.
*
* @param domain
* a SCOP domain
* @param scopDatabase
* A {@link ScopDatabase} to use
* @return a Structure object
* @throws IOException
* @throws StructureException
*/
public Structure getStructureForDomain(ScopDomain domain, ScopDatabase scopDatabase) throws IOException,
StructureException {
return getStructureForDomain(domain, scopDatabase, false);
}
/**
* Returns the representation of a {@link ScopDomain} as a BioJava {@link Structure} object.
*
* @param domain
* a SCOP domain
* @param scopDatabase
* A {@link ScopDatabase} to use
* @param strictLigandHandling
* If set to false, hetero-atoms are included if and only if they belong to a chain to which the SCOP
* domain belongs; if set to true, hetero-atoms are included if and only if they are strictly within the
* definition (residue numbers) of the SCOP domain
* @return a Structure object
* @throws IOException
* @throws StructureException
*/
public Structure getStructureForDomain(ScopDomain domain, ScopDatabase scopDatabase, boolean strictLigandHandling)
throws IOException, StructureException {
PdbId pdbId = domain.getPdbId();
Structure fullStructure = getStructureForPdbId(pdbId);
Structure structure = domain.reduce(fullStructure);
// TODO It would be better to move all of this into the reduce method,
// but that would require ligand handling properties in StructureIdentifiers
// because ligands sometimes occur after TER records in PDB files, we may need to add some ligands back in
// specifically, we add a ligand if and only if it occurs within the domain
AtomPositionMap map = null;
List rrs = null;
if (strictLigandHandling) {
map = new AtomPositionMap(StructureTools.getAllAtomArray(fullStructure), AtomPositionMap.ANYTHING_MATCHER);
rrs = ResidueRangeAndLength.parseMultiple(domain.getRanges(), map);
}
for (Chain chain : fullStructure.getNonPolyChains()) {
if (!structure.hasPdbChain(chain.getName())) {
continue; // we can't do anything with a chain our domain
}
Chain newChain;
if (!structure.hasNonPolyChain(chain.getId())) {
newChain = new ChainImpl();
newChain.setId(chain.getId());
newChain.setName(chain.getName());
newChain.setEntityInfo(chain.getEntityInfo());
structure.addChain(newChain);
} else {
newChain = structure.getNonPolyChain(chain.getId());
}
List ligands = StructureTools.filterLigands(chain.getAtomGroups());
for (Group group : ligands) {
boolean shouldContain = true;
if (strictLigandHandling) {
shouldContain = false; // whether the ligand occurs within the domain
for (ResidueRange rr : rrs) {
if (rr.contains(group.getResidueNumber(), map)) {
shouldContain = true;
}
}
}
boolean alreadyContains = newChain.getAtomGroups().contains(group); // we don't want to add duplicate
// ligands
if (shouldContain && !alreadyContains) {
newChain.addGroup(group);
}
}
}
// build a more meaningful description for the new structure
StringBuilder header = new StringBuilder();
header.append(domain.getClassificationId());
if (scopDatabase != null) {
int sf = domain.getSuperfamilyId();
ScopDescription description = scopDatabase.getScopDescriptionBySunid(sf);
if (description != null) {
header.append(" | ");
header.append(description.getDescription());
}
}
structure.getPDBHeader().setDescription(header.toString());
return structure;
}
/**
* Returns the representation of a {@link ScopDomain} as a BioJava {@link Structure} object.
*
* @param scopId
* a SCOP Id
* @return a Structure object
* @throws IOException
* @throws StructureException
*/
public Structure getStructureForDomain(String scopId) throws IOException, StructureException {
return getStructureForDomain(scopId, ScopFactory.getSCOP());
}
/**
* Returns the representation of a {@link ScopDomain} as a BioJava {@link Structure} object.
*
* @param scopId
* a SCOP Id
* @param scopDatabase
* A {@link ScopDatabase} to use
* @return a Structure object
* @throws IOException
* @throws StructureException
*/
public Structure getStructureForDomain(String scopId, ScopDatabase scopDatabase) throws IOException,
StructureException {
ScopDomain domain = scopDatabase.getDomainByScopID(scopId);
return getStructureForDomain(domain, scopDatabase);
}
/**
* set the location at which utility data should be cached.
*
* @param cachePath
*/
public void setCachePath(String cachePath) {
this.cachePath = cachePath;
}
public void setFileParsingParams(FileParsingParameters params) {
this.params = params;
}
/**
* [Optional] This method changes the behavior when obsolete entries
* are requested. Current behaviors are:
*
* - {@link ObsoleteBehavior#THROW_EXCEPTION THROW_EXCEPTION}
* Throw a {@link StructureException} (the default)
*
- {@link ObsoleteBehavior#FETCH_OBSOLETE FETCH_OBSOLETE}
* Load the requested ID from the PDB's obsolete repository
*
- {@link ObsoleteBehavior#FETCH_CURRENT FETCH_CURRENT}
* Load the most recent version of the requested structure
*
*
* This setting may be silently ignored by implementations which do not have
* access to the server to determine whether an entry is obsolete, such as
* certain {@link FetchBehavior}s. Note that an obsolete entry may still be
* returned even this is FETCH_CURRENT if the entry is found locally.
*
* @param behavior Whether to fetch obsolete records
* @since 4.0.0
*/
public void setObsoleteBehavior(ObsoleteBehavior behavior) {
obsoleteBehavior = behavior;
}
/**
* Returns how this instance deals with obsolete entries. Note that this
* setting may be ignored by some implementations or in some situations,
* such as certain {@link FetchBehavior}s.
*
*
For most implementations, the default value is
* {@link ObsoleteBehavior#THROW_EXCEPTION THROW_EXCEPTION}.
*
* @return The ObsoleteBehavior
* @since 4.0.0
*/
public ObsoleteBehavior getObsoleteBehavior() {
return obsoleteBehavior;
}
/**
* Get the behavior for fetching files from the server
* @return
*/
public FetchBehavior getFetchBehavior() {
return fetchBehavior;
}
/**
* Set the behavior for fetching files from the server
* @param fetchBehavior
*/
public void setFetchBehavior(FetchBehavior fetchBehavior) {
this.fetchBehavior = fetchBehavior;
}
/**
* Set the path that is used to cache PDB files.
*
* @param path
* to a directory
*/
public void setPath(String path) {
this.path = FileDownloadUtils.expandUserHome(path);
}
/**
* Returns the currently active file type that will be parsed.
* @return a StructureFiletype
*/
public StructureFiletype getFiletype() {
return filetype;
}
/**
* Set the file type that will be parsed.
* @param filetype a StructureFiletype
*/
public void setFiletype(StructureFiletype filetype) {
this.filetype = filetype;
}
private boolean checkLoading(PdbId pdbId) {
return currentlyLoading.contains(pdbId.getId());
}
/**
* Returns a {@link Structure} corresponding to the CATH identifier supplied in {@code structureName}, using the the {@link CathDatabase}
* at {@link CathFactory#getCathDatabase()}.
*/
public Structure getStructureForCathDomain(StructureName structureName) throws IOException, StructureException {
return getStructureForCathDomain(structureName, CathFactory.getCathDatabase());
}
/**
* Returns a {@link Structure} corresponding to the CATH identifier supplied in {@code structureName}, using the specified {@link CathDatabase}.
*/
public Structure getStructureForCathDomain(StructureName structureName, CathDatabase cathInstall) throws IOException, StructureException {
CathDomain cathDomain = cathInstall.getDomainByCathId(structureName.getIdentifier());
Structure s = getStructureForPdbId(cathDomain.getIdentifier());
Structure n = cathDomain.reduce(s);
// add the ligands of the chain...
Chain newChain = n.getPolyChainByPDB(structureName.getChainId());
List origChains = s.getNonPolyChainsByPDB(structureName.getChainId());
for (Chain origChain : origChains) {
List ligands = origChain.getAtomGroups();
for (Group g : ligands) {
if (!newChain.getAtomGroups().contains(g)) {
newChain.addGroup(g);
}
}
}
return n;
}
protected void flagLoading(PdbId pdbId) {
String id = pdbId.getId();
if (!currentlyLoading.contains(id)) {
currentlyLoading.add(id);
}
}
protected void flagLoadingFinished(PdbId pdbId) {
currentlyLoading.remove(pdbId.getId());
}
/**
* Loads a structure directly by PDB ID
* @param id
* @return
* @throws IOException
* @throws StructureException
*/
public Structure getStructureForPdbId(String id) throws IOException, StructureException {
if (id == null)
return null;
return getStructureForPdbId(new PdbId(id));
}
/**
* Loads a structure directly by PDB ID
* @param pdbId
* @return
* @throws IOException
*/
public Structure getStructureForPdbId(PdbId pdbId) throws IOException {
if (pdbId == null)
return null;
while (checkLoading(pdbId)) {
// waiting for loading to be finished...
try {
Thread.sleep(100);
} catch (InterruptedException e) {
logger.error(e.getMessage());
}
}
switch (filetype) {
case CIF:
logger.debug("loading from mmcif");
return loadStructureFromCifByPdbId(pdbId);
case BCIF:
logger.debug("loading from bcif");
return loadStructureFromBcifByPdbId(pdbId);
case PDB: default:
logger.debug("loading from pdb");
return loadStructureFromPdbByPdbId(pdbId);
}
}
protected Structure loadStructureFromCifByPdbId(String pdbId) throws IOException {
return loadStructureFromCifByPdbId(new PdbId(pdbId));
}
protected Structure loadStructureFromCifByPdbId(PdbId pdbId) throws IOException {
logger.debug("Loading structure {} from mmCIF file {}.", pdbId, path);
Structure s;
flagLoading(pdbId);
try {
CifFileReader reader = new CifFileReader(path);
reader.setFetchBehavior(fetchBehavior);
reader.setObsoleteBehavior(obsoleteBehavior);
reader.setFileParsingParameters(params);
s = reader.getStructureById(pdbId);
} finally {
flagLoadingFinished(pdbId);
}
return s;
}
protected Structure loadStructureFromBcifByPdbId(String pdbId) throws IOException {
return loadStructureFromBcifByPdbId(new PdbId(pdbId));
}
protected Structure loadStructureFromBcifByPdbId(PdbId pdbId) throws IOException {
logger.debug("Loading structure {} from BinaryCIF file {}.", pdbId, path);
Structure s;
flagLoading(pdbId);
try {
BcifFileReader reader = new BcifFileReader(path);
reader.setFetchBehavior(fetchBehavior);
reader.setObsoleteBehavior(obsoleteBehavior);
reader.setFileParsingParameters(params);
s = reader.getStructureById(pdbId);
} finally {
flagLoadingFinished(pdbId);
}
return s;
}
protected Structure loadStructureFromPdbByPdbId(String pdbId) throws IOException {
return loadStructureFromPdbByPdbId(new PdbId(pdbId));
}
protected Structure loadStructureFromPdbByPdbId(PdbId pdbId) throws IOException {
logger.debug("Loading structure {} from PDB file {}.", pdbId, path);
Structure s;
flagLoading(pdbId);
try {
PDBFileReader reader = new PDBFileReader(path);
reader.setFetchBehavior(fetchBehavior);
reader.setObsoleteBehavior(obsoleteBehavior);
reader.setFileParsingParameters(params);
s = reader.getStructureById(pdbId);
} finally {
flagLoadingFinished(pdbId);
}
return s;
}
}