001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.quaternary.io;
022
023import org.biojava.nbio.structure.Structure;
024import org.biojava.nbio.structure.StructureTools;
025import org.biojava.nbio.structure.align.util.AtomCache;
026import org.biojava.nbio.structure.io.FileParsingParameters;
027import org.biojava.nbio.structure.io.MMCIFFileReader;
028import org.biojava.nbio.structure.io.mmcif.SimpleMMcifConsumer;
029import org.biojava.nbio.structure.io.mmcif.model.PdbxStructAssembly;
030import org.biojava.nbio.structure.io.mmcif.model.PdbxStructAssemblyGen;
031import org.biojava.nbio.structure.io.mmcif.model.PdbxStructOperList;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035import java.io.IOException;
036import java.util.ArrayList;
037import java.util.Iterator;
038import java.util.List;
039
040
041
042/** A provider for information about biological units for PDB files that is based on reading local MMcif files.
043 *
044 * @author Andreas Prlic
045 *
046 */
047public class MmCifPDBBiolAssemblyProvider implements RawBioUnitDataProvider{
048
049        private static final Logger logger = LoggerFactory.getLogger(MmCifPDBBiolAssemblyProvider.class);
050
051        private String pdbId;
052        private List<PdbxStructAssembly> pdbxStructAssemblies;
053        private List<PdbxStructAssemblyGen> pdbxStructAssemblyGens;
054        private List<PdbxStructOperList> pdbxStructOperList;
055        private Structure asymUnit;
056
057        private AtomCache cache ;
058
059        public MmCifPDBBiolAssemblyProvider(){
060                //reset();
061        }
062
063        @Override
064        public void setPdbId(String pdbId) {
065                if ( cache == null)
066                        cache =new AtomCache();
067
068                if (
069                                this.pdbId != null &&
070                                (this.pdbId.equals(pdbId))
071                                ) {
072                        // we already have all the data we need...
073                        return;
074                }
075
076                this.pdbId= pdbId;
077
078                reset();
079
080                MMCIFFileReader reader = new MMCIFFileReader(cache.getPath());
081                FileParsingParameters params = cache.getFileParsingParams();
082                params.setAlignSeqRes(true);
083                params.setParseBioAssembly(true);
084                reader.setFileParsingParameters(params);
085                reader.setFetchBehavior(cache.getFetchBehavior());
086                reader.setObsoleteBehavior(cache.getObsoleteBehavior());
087
088                try{
089                        asymUnit = reader.getStructureById(pdbId);
090                        if ( asymUnit.nrModels() > 1) {
091                                // why do some NMR structures have bio units???
092                                asymUnit = StructureTools.removeModels(asymUnit);
093                        }
094
095                        SimpleMMcifConsumer consumer = reader.getMMcifConsumer();
096
097
098                        pdbxStructOperList              = consumer.getStructOpers();
099                        pdbxStructAssemblies    = consumer.getStructAssemblies();
100                        pdbxStructAssemblyGens  = consumer.getStructAssemblyGens();
101
102                        //System.out.println(asymUnit.getPDBHeader());
103
104                        //System.out.println("OPER:" + pdbxStructOperList);
105                        //System.out.println("ASSEMBLIES:" + pdbxStructAssemblies);
106                        //System.out.println("ASSEMBLYGENS:" + pdbxStructAssemblyGens);
107
108                        // reset the consumer data to avoid memory leaks
109                        consumer.documentStart();
110
111
112                        // here we trim in the same way as we do in SimpleMmcifConsumer, removing PAU and XAU bioassemblies, see #230 in github
113                        Iterator<PdbxStructAssembly> it = pdbxStructAssemblies.iterator();
114                        while (it.hasNext()) {
115                                PdbxStructAssembly psa = it.next();
116                                try {
117                                        Integer.parseInt(psa.getId());
118                                } catch (NumberFormatException e) {
119                                        logger.info("Ignoring bioassembly with id {} for PDB id {}", psa.getId(), pdbId);
120                                        it.remove();
121                                }
122                        }
123
124                } catch (IOException e){
125                        // TODO this should be thrown but setPdbId doesn't have a throws in contract, we need a better solution - JD 2016-01-27
126                        logger.error("IOException caught when reading mmcif file to get bioassembly for PDB " + pdbId, e);
127
128                }
129        }
130
131        private void reset() {
132
133                pdbxStructOperList      = new ArrayList<PdbxStructOperList>();
134                pdbxStructAssemblies    = new ArrayList<PdbxStructAssembly>();
135                pdbxStructAssemblyGens  = new ArrayList<PdbxStructAssemblyGen>();
136                asymUnit = null;
137        }
138
139        public String getPdbId(){
140                return pdbId;
141        }
142
143        @Override
144        public List<PdbxStructAssembly> getPdbxStructAssemblies() {
145                return pdbxStructAssemblies;
146        }
147
148        @Override
149        public List<PdbxStructAssemblyGen> getPdbxStructAssemblyGens() {
150                return pdbxStructAssemblyGens;
151        }
152
153        @Override
154        public List<PdbxStructOperList> getPdbxStructOperList() {
155                return pdbxStructOperList;
156        }
157
158        @Override
159        public int getNrBiolAssemblies() {
160                return pdbxStructAssemblies.size();
161        }
162
163        @Override
164        public boolean hasBiolAssembly() {
165                int nrAssemblies = getNrBiolAssemblies();
166                if ( nrAssemblies > 0)
167                        return true;
168
169                return false;
170        }
171
172        @Override
173        public PdbxStructAssembly getPdbxStructAssembly(int biolAssemblyNr) {
174                if ( biolAssemblyNr < getNrBiolAssemblies())
175                        return pdbxStructAssemblies.get(biolAssemblyNr);
176                return null;
177        }
178
179        @Override
180        public List<PdbxStructAssemblyGen> getPdbxStructAssemblyGen(int biolAssemblyNr) {
181                if ( biolAssemblyNr > getNrBiolAssemblies())
182                        return null;
183
184                List<PdbxStructAssemblyGen> psags = new ArrayList<PdbxStructAssemblyGen>();
185                for (PdbxStructAssemblyGen psag : pdbxStructAssemblyGens){
186                        if ( psag.getAssembly_id().equals((biolAssemblyNr +1)+ ""))
187                                psags.add(psag);
188                }
189                return psags;
190        }
191
192        /** get the asym unit for this PDB ID
193         *
194         * @return
195         */
196        public Structure getAsymUnit(){
197                return asymUnit;
198        }
199
200        public void setAsymUnit(Structure s){
201                this.asymUnit = s;
202        }
203
204        public AtomCache getAtomCache() {
205                return cache;
206        }
207
208        public void setAtomCache(AtomCache cache) {
209                this.cache = cache;
210        }
211
212
213
214}