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 * Created on 26.04.2004
021 * @author Andreas Prlic
022 *
023 */
024package org.biojava.nbio.structure;
025
026import org.biojava.nbio.structure.io.FileConvert;
027import org.biojava.nbio.structure.io.PDBFileReader;
028
029import java.io.Serializable;
030import java.util.List;
031
032
033/**
034 * Interface for a structure object. Provides access to the data of a PDB file.
035 * <p>
036 * A structure object allows to access the PDB header information as well
037 * as to the data from the ATOM records. The header information is
038 * currently available through the following objects:
039 * <ul>
040 * <li>{@link PDBHeader}</li>
041 * <li>{@link DBRef}</li>
042 * <li>{@link EntityInfo}</li>
043 * </ul>
044 *
045 * The structure object provides access to the data from the ATOM records through
046 * a hierarchy of sub-object:
047 * <pre>
048 * Structure
049 *         |
050 *         {@link Chain}
051 *             |
052 *             {@link Group}
053 *                 |
054 *                 {@link Atom}
055 * </pre>
056 *
057 * For more documentation on how to work with the Structure API please
058 * see <a href="http://biojava.org/wiki/BioJava:CookBook#Protein_Structure" target="_top">
059 * http://biojava.org/wiki/BioJava:CookBook#Protein_Structure</a>
060 *
061 * <p>
062 *  The tutorial for the BioJava structure modules can be found at <a href="https://github.com/biojava/biojava3-tutorial/tree/master/structure">github</a>.
063 * <hr/>
064 * <p>
065 * Q: How can I get a Structure object from a PDB file?
066 * <p>
067 * A:
068 * <pre>
069 *  Structure loadStructure(String pathToPDBFile) {
070 *              PDBFileReader pdbreader = new PDBFileReader();
071 *              Structure structure = pdbreader.getStructure(pathToPDBFile);
072 *              System.out.println(structure);
073 *              return structure;
074 *      }
075 *  </pre>
076 *
077 * <hr>
078 * <p>
079 * Q: How can I calculate Phi and Psi angles of AminoAcids?
080 * <p>
081 * A:
082 * <pre>{@code
083 *  void calcPhiPsi(Structure structure) {
084 *
085 *              // get the first chain from the structure
086 *              Chain chain  = structure.getChain(0);
087 *
088 *              // A protein chain consists of a number of groups. These can be either
089 *              // AminoAcid, HetatomImpl or NucleotideImpl groups.
090 *              //
091 *              // Note: BioJava provides access to both the ATOM and SEQRES data in a PDB file.
092 *              // since we are interested in doing calculations here, we only request the groups
093 *              // from the ATOM records
094 *
095 *              //  get the Groups of the chain that are AminoAcids.
096 *              List<Group> groups = chain.getAtomGroups(GroupType.AMINOACID);
097 *
098 *              AminoAcid a;
099 *              AminoAcid b;
100 *              AminoAcid c;
101 *              for (int i=0; i < groups.size(); i++) {
102 *                      // since we requested only groups of type AMINOACID they will always be amino acids
103 *                      // Nucleotide and Hetatom groups will not be present in the groups list.
104 *                      b = (AminoAcid)groups.get(i);
105 *                      double phi = 360.0;
106 *                      double psi = 360.0;
107 *
108 *                      if (i > 0) {
109 *                              a = (AminoAcid)groups.get(i-1) ;
110 *                              // the Calc class provides utility methods for various calculations on
111 *                              // structures, groups and atoms
112 *                              phi = Calc.getPhi(a,b);
113 *                      }
114 *                      if (i < groups.size()-1) {
115 *                              c = (AminoAcid)groups.get(i+1) ;
116 *                              psi = Calc.getPsi(b, c);
117 *                      }
118 *                      System.out.print(b.getPDBCode() + " " + b.getPDBName() + ":"  );
119 *                      System.out.println(String.format("\tphi: %+7.2f psi: %+7.2f", phi, psi));
120 *              }
121 *      }
122 * }</pre>
123 * <hr>
124 *
125 * @author Andreas Prlic
126 * @since 1.4
127 */
128public interface Structure extends Cloneable, Serializable {
129
130
131        /**
132         * Return an identical copy of this Structure object
133         *
134         * @return identical copy of this Structure object
135         */
136        Structure clone();
137
138        /**
139         * String representation of object.
140         */
141        @Override
142        String toString();
143
144        /**
145         * Set biological name of Structure .
146         *
147         * @param name  a String specifying the biological name of the Structure
148         * @see #getName
149         */
150        void setName(String name);
151
152        /**
153         * Get biological name of Structure.
154         *
155         * @return a String representing the biological name of the Structure
156         * @see #setName
157         */
158        String getName();
159
160        /**
161         * Get an identifier corresponding to this structure
162         * @return The StructureIdentifier used to create this structure
163         */
164        StructureIdentifier getStructureIdentifier();
165
166        /**
167         * Set the identifier corresponding to this structure
168         * @param structureIdentifier the structureIdentifier corresponding to this structure
169         */
170        void setStructureIdentifier(StructureIdentifier structureIdentifier);
171
172        /**
173         * Return number of polymer Chains in this Structure for first model.
174         * @return the number of polymer Chains in this Structure
175         */
176        int size() ;
177
178        /**
179         * Return number of chains of model.
180         *
181         * @param modelnr  an int specifying the number of the Model that should be used
182         * @return an int representing the number of Chains in this Model
183         */
184        int size(int modelnr);
185
186        /**
187         * Return the number of models .
188         * In this implementation also XRAY structures have "1 model", since
189         * model is the container for the chains.
190         * to test if a Structure is an NMR structure use {@link #isNmr()}.
191         *
192         * @return an int representing the number of models in this Structure
193         * @see #isNmr()
194         */
195        int nrModels() ;
196
197        /**
198         * Test if this structure is an NMR structure.
199         *
200         * @return true if this Structure has been solved by NMR
201         * @see #nrModels()
202         */
203        boolean isNmr() ;
204
205        /**
206         * Test if this structure is a crystallographic structure, i.e. it is an asymmetric unit
207         * from which it is possible to reconstruct the crystal lattice given cell parameters and
208         * space group.
209         *
210         * @return true if crystallographic, false otherwise
211         */
212        boolean isCrystallographic();
213
214        /**
215         * Add a new model.
216         *
217         * @param model  a List object containing the Chains of the new Model
218         */
219        void addModel(List<Chain> model);
220
221
222        /**
223         * A convenience function if one wants to edit and replace the
224         * models in a structure. Allows to set (replace) the model at position
225         * with the new List of Chains.
226         * @param position starting at 0
227         * @param model list of chains representing a model
228         */
229        void setModel(int position, List<Chain> model);
230
231        /**
232         * Retrieve all Chains belonging to a model .
233         * @see #getChains(int modelnr)
234         *
235         * @param modelnr  an int
236         * @return a List object containing the Chains of Model nr. modelnr
237         */
238        List<Chain> getModel(int modelnr);
239
240        /**
241         * Retrieve all chains for the first model.
242         * This is the same as getChains(0);
243         * @see #getModel(int modelnr)
244         * @see #getChains(int modelnr)
245         *
246         * @return a List object containing the Chains of Model nr. modelnr
247         */
248        List<Chain> getChains();
249
250        /**
251         * Set the chains of a structure, if this is a NMR structure,
252         * this will only set model 0.
253         *
254         * @see #setChains(int, List)
255         *
256         * @param chains the list of chains for this structure.
257         */
258        void setChains(List<Chain> chains);
259
260        /**
261         * Retrieve all chains of a model.
262         * @see #getModel
263         *
264         * @param modelnr  an int
265         * @return a List object containing the Chains of Model nr. modelnr
266         */
267        List<Chain> getChains(int modelnr);
268
269        /**
270         * Set the chains for a model
271         * @param chains the chains for a model
272         * @param modelnr the number of the model
273         */
274        void setChains( int modelnr, List<Chain> chains);
275
276        /**
277         * Return all polymeric chains for the first model
278         *
279         * @return all polymeric chains.
280         * @since 5.0
281         */
282        List<Chain> getPolyChains();
283
284        /**
285         * Return all polymeric chains for the given model index.
286         * @param modelIdx the model index
287         * @return all polymeric chains.
288         * @since 5.0
289         */
290        List<Chain> getPolyChains(int modelIdx);
291
292        /**
293         * Return all non-polymeric chains for the first model
294         *
295         * @return all non-polymeric chains.
296         * @since 5.0
297         */
298        List<Chain> getNonPolyChains();
299
300        /**
301         * Return all non-polymeric chains for the given model index.
302         *
303         * @param modelIdx the model index
304         * @return all non-polymeric chains.
305         * @since 5.0
306         */
307        List<Chain> getNonPolyChains(int modelIdx);
308
309        /**
310         * Return all water chains for the first model
311         * @return
312         * @since 5.0
313         */
314        List<Chain> getWaterChains();
315
316        /**
317         * Return all water chains for the given model index
318         * @param modelIdx
319         * @return
320         * @since 5.0
321         */
322        List<Chain> getWaterChains(int modelIdx);
323
324        /**
325         * Add a new chain to the first model
326         *
327         * @param chain  a Chain object
328         */
329        void addChain(Chain chain);
330
331        /**
332         * Add a new chain to the model specified by the given index
333         *
334         * @param chain    a Chain object
335         * @param modelnr  an int specifying to which model the Chain should be added
336         */
337        void addChain(Chain chain, int modelnr);
338
339        /**
340         * Retrieve a chain by its index within the Structure .
341         *
342         * @param chainIndex the index of the desired chain in the structure
343         * @return a Chain object
344         */
345        Chain getChainByIndex(int chainIndex);
346
347        /**
348         * Retrieve a chain by its indices within the Structure and model.
349         *
350         * @param chainIndex the index of the desired chain in the structure
351         * @param modelnr the model the desired chain is in
352         * @return a Chain object
353         */
354        Chain getChainByIndex(int modelnr, int chainIndex);
355
356        /**
357         * Check if a chain with the chainId aymId is contained in this structure.
358         *
359         * @param asymId the Id of the chain
360         * @return true if a chain with the id asymId is found
361         */
362        boolean hasChain(String asymId);
363
364        /**
365         * Check if a non polymeric chain with chainId asymId is contained in the structure.
366         *
367         * @param asymId the id of the chain
368         * @return true if a nonpolymeric chain with the asymId is found
369         * @since 5.0
370         */
371        boolean hasNonPolyChain(String asymId);
372
373
374        /**
375         * Check if a chain  with chain name authId is contained in the structure
376         *
377         * @param authId the chain name
378         * @return true if a chain with the name authId is found
379         */
380        boolean hasPdbChain(String authId) ;
381
382        /**
383         * Request a particular group from a structure.
384         * by default considers only the first model in the structure.
385         * @param authId the name of the chain to use
386         * @param pdbResnum the PDB residue number of the requested group
387         * @return Group the requested Group
388         * @throws StructureException
389         */
390        Group findGroup(String authId, String pdbResnum) throws StructureException;
391
392        /**
393         * Request a particular group from a structure.
394         * considers only model nr X. count starts with 0.
395         * @param authId the chain name of the chain to use
396         * @param pdbResnum the PDB residue number of the requested group
397         * @param modelnr the number of the model to use
398         * @return Group the requested Group
399         * @throws StructureException
400         */
401        Group findGroup(String authId, String pdbResnum, int modelnr) throws StructureException;
402
403        /**
404         * Retrieve a Chain (polymeric, non-polymeric or water) based on
405         * the 'internal' chain id (asymId) for the first model
406         * @param asymId the asymId (chainId)
407         * @return
408         * @see #getPolyChain(String)
409         * @see #getNonPolyChain(String)
410         * @see #getWaterChain(String)
411         */
412        Chain getChain(String asymId);
413
414        /**
415         * Retrieve a Chain (polymeric, non-polymeric or water) based on
416         * the 'internal' chain id (asymId) for the given model index
417         * @param asymId the asymId (chainId)
418         * @param modelIdx the index of the required model (0-based)
419         * @return
420         * @see #getPolyChain(String, int)
421         * @see #getNonPolyChain(String, int)
422         * @see #getWaterChain(String, int)
423         */
424        Chain getChain(String asymId, int modelIdx);
425
426        /**
427         * Retrieve a polymeric Chain based on the 'internal' chain
428         * id (asymId) for the first model
429         *
430         * <p>See {@link #getPolyChainByPDB(String)} for a similar
431         * method using the chain name (authId).
432         * @param asymId the asymId (chainId)
433         * @return a polymeric Chain or null if it can't be found
434         * @since 5.0
435         */
436        Chain getPolyChain(String asymId);
437
438        /**
439         * Retrieve a polymeric Chain based on the 'internal' chain
440         * id (asymId) for the given model index
441         *
442         * <p>See {@link #getPolyChainByPDB(String, int)} for a similar
443         * method using the chain name (authId).
444         * @param asymId the asymId (chainId)
445         * @param modelIdx the index of the required model (0-based)
446         * @return a polymeric Chain or null if it can't be found
447         * @since 5.0
448         */
449        Chain getPolyChain(String asymId, int modelIdx);
450
451        /**
452         * Retrieve a polymeric Chain based on the 'public' chain
453         * name (authId) for the first model
454         *
455         * <p>See {@link #getPolyChain(String)} for a similar
456         * method using the chain id (asymId).
457         * @param authId the author id (chainName, public chain id)
458         * @return a polymeric Chain or null if it can't be found
459         * @since 5.0
460         */
461        Chain getPolyChainByPDB(String authId);
462
463        /**
464         * Retrieve a polymeric Chain based on the 'public' chain
465         * name (authId) for the given model index.
466         *
467         * <p>See {@link #getPolyChain(String, int)} for a similar
468         * method using the chain id (asymId).
469         * @param authId the author id (chainName, public chain id)
470         * @param modelIdx the index of the required model (0-based)
471         * @return a polymeric Chain or null if it can't be found
472         * @since 5.0
473         *
474         */
475        Chain getPolyChainByPDB(String authId, int modelIdx);
476
477
478        /**
479         * Retrieve a non-polymeric Chain based on the 'internal' chain
480         * id (asymId) for the first model
481         * @param asymId the asymId (chainId)
482         * @return a non-polymeric chain or null if it can't be found
483         * @since 5.0
484         */
485        Chain getNonPolyChain(String asymId);
486
487        /**
488         * Retrieve a non-polymeric Chain based on the 'internal' chain
489         * id (asymId) for the given model index
490         * @param asymId the asymId (chainId)
491         * @param modelIdx the index of the required model (0-based)
492         * @return a non-polymeric Chain or null if it can't be found
493         * @since 5.0
494         */
495        Chain getNonPolyChain(String asymId, int modelIdx);
496
497        /**
498         * Retrieve all non-polymeric Chains corresponding to the given 'public' chain
499         * name (authId) for the first model.
500         * @param authId the author id (chainName, public chain id)
501         * @return a list of non-polymeric Chains, if none found the list will be empty
502         * @since 5.0
503         */
504        List<Chain> getNonPolyChainsByPDB(String authId);
505
506        /**
507         * Retrieve all non-polymeric Chains corresponding to the 'public' chain
508         * name (authId) and the given model index.
509         * @param authId the author id (chainName, public chain id)
510         * @param modelIdx the index of the required model (0-based)
511         * @return a list of non-polymeric Chains, if none found the list will be empty
512         * @since 5.0
513         */
514        List<Chain> getNonPolyChainsByPDB(String authId, int modelIdx);
515
516        /**
517         * Retrieve a water Chain based on the 'internal' chain id (asymId)
518         * for the first model
519         * @param asymId the asymId (chainId)
520         * @return a water Chain or null if it can't be found
521         * @since 5.0
522         */
523        Chain getWaterChain(String asymId);
524
525        /**
526         * Retrieve a water chain based on the 'internal' chain id (asymId)
527         * for the given model index
528         * @param asymId the asymId (chainId)
529         * @param modelIdx the index of the required model (0-based)
530         * @return
531         * @since 5.0
532         */
533        Chain getWaterChain(String asymId, int modelIdx);
534
535        /**
536         * Retrieve a water Chain based on the 'public' chain name (authId)
537         * for the first model
538         * @param authId the author id (chainName, public chain id)
539         * @return
540         * @since 5.0
541         */
542        Chain getWaterChainByPDB(String authId);
543
544        /**
545         * Retrieve a water Chain based on the 'public' chain name (authId)
546         * for the given model index
547         * @param authId the author id (chainName, public chain id)
548         * @param modelIdx the index of the required model (0-based)
549         * @return
550         * @since 5.0
551         */
552        Chain getWaterChainByPDB(String authId, int modelIdx);
553
554
555        /**
556         * Create a String that contains this Structure's contents in PDB file format.
557         *
558         * @return a String that looks like a PDB file
559         * @see FileConvert
560         */
561        String toPDB();
562
563        /**
564         * Create a String that contains this Structure's contents in MMCIF file format.
565         * @return a String representation of the Structure object in mmCIF.
566         */
567        String toMMCIF();
568
569        /**
570         * Set the EntityInfo
571         *
572         * @param molList list of entityinfo objects
573         */
574        void setEntityInfos(List<EntityInfo> molList);
575
576        /**
577         * Get all the EntityInfo for this Structure.
578         *
579         * @return a list of EntityInfos
580         */
581        List<EntityInfo> getEntityInfos();
582
583        /**
584         * Add an EntityInfo to this Structure
585         */
586        void addEntityInfo(EntityInfo entityInfo);
587
588        /**
589         * Set the list of database references for this structure
590         * @param dbrefs list of DBRef objects
591         *
592         */
593        void setDBRefs(List<DBRef> dbrefs);
594
595        /**
596         * Get the list of database references
597         *
598         * @return list of DBRef objects
599         */
600        List<DBRef> getDBRefs();
601
602        /**
603         * Request a particular entity by its entity id (mol id in legacy PDB format)
604         *
605         * @param entityId the number of the entity
606         * @return an entity, or null if the molId was not found
607         */
608        EntityInfo getEntityById(int entityId);
609
610        /**
611         * Return the header information for this PDB file.
612         * <b>N.B.</b> Take care when you blindly use the returned object from this method,
613         * because it might be null in some cases.
614         *
615         * @return the PDBHeader object
616         */
617        PDBHeader getPDBHeader();
618
619        /**
620         * Return whether or not the entry has an associated journal article
621         * or ation. The JRNL section is not mandatory and thus may not be
622         * present.
623         * @return flag if a JournalArticle has been found.
624         */
625        boolean hasJournalArticle();
626
627        /**
628         * Get the associated publication as defined by the JRNL records in a PDB
629         * file.
630         * @return a JournalArticle
631         */
632        JournalArticle getJournalArticle();
633
634        /**
635         * Set the associated publication as defined by the JRNL records in a PDB
636         * file.
637         * @param journalArticle a JournalArticle object
638         */
639        void setJournalArticle(JournalArticle journalArticle);
640
641        /**
642         * Get the list of disulfide Bonds as they have been defined in the PDB files
643         *
644         * @return a list of Bonds
645         */
646        List<Bond> getSSBonds();
647
648        /**
649         * Set the list of SSBonds for this structure
650         *
651         * @param ssbonds
652         */
653        void setSSBonds(List<Bond> ssbonds);
654
655        /**
656         * Add a single disulfide Bond to this structure
657         *
658         * @param ssbond a disulfide bond
659         */
660        void addSSBond(Bond ssbond);
661
662        /**
663         * Set the the header information for this PDB file
664         *
665         * @param header the PDBHeader object
666         */
667        void setPDBHeader(PDBHeader header);
668
669        /**
670         * @param sites the sites to set in the structure
671         */
672        void setSites(List<Site> sites);
673
674        /**
675         * @return the sites contained in this structure
676         */
677        List<Site> getSites();
678
679        /**
680         * Set a flag to indicate if this structure is a biological assembly
681         * @param biologicalAssembly true if biological assembly, otherwise false
682         * @since 3.2
683         */
684        void setBiologicalAssembly(boolean biologicalAssembly);
685
686        /**
687         * Get flag that indicates if this structure is a biological assembly
688         * @return  true if biological assembly, otherwise false
689         * @since 3.2
690         */
691        boolean isBiologicalAssembly();
692
693        /**
694         * Set crystallographic information for this structure
695         * @param crystallographicInfo crystallographic information
696         * @since 3.2
697         */
698        void setCrystallographicInfo(PDBCrystallographicInfo crystallographicInfo);
699
700        /**
701         * Get crystallographic information for this structure
702         * @return PDBCrystallographicInfo crystallographic information
703         * @since 3.2
704         */
705        PDBCrystallographicInfo getCrystallographicInfo();
706
707        /**
708         * Resets all models of this Structure
709         * @since 4.0.1
710         */
711        void resetModels();
712
713        /**
714         * Get a string representing this structure's contents. The following places
715         * are searched for a non-null value, with the first being returned:
716         * <ol>
717         * <li>{@link #getStructureIdentifier()}.getIdentifier(), which should give
718         *     the string originally used to create the structure
719         * <li>{@link #getName()}
720         * <li>A combination of {@link #getPDBCode()} with a heuristic description
721         *     of the residue ranges, in {@link SubstructureIdentifier} format.
722         * </ol>
723         * @return A {@link SubstructureIdentifier}-format string describing the residue ranges in this structure
724         * @since The behavior of this method changed in BioJava 4.2. Previously it
725         *  returned the same value as {@link #getPDBCode()}
726         */
727        String getIdentifier();
728
729        /**
730         * Get PDB code of structure.
731         *
732         * @return a String representing the PDBCode value
733         * @see #setPDBCode
734         * @deprecated use {@link #getPdbId()} to get a {@link PdbId} object or getPdbId().getId() to get a {@link String}
735         */
736        @Deprecated
737        String getPDBCode () ;
738
739        /**
740         * Set PDB code of structure .
741         *
742         * @param pdb_id  a String specifying the PDBCode
743         * @see #getPDBCode
744         * @deprecated use {@link #setPdbId(PdbId)}
745         */
746        @Deprecated
747        void setPDBCode (String pdb_id);
748
749        /**
750         * Returns the PDB identifier associated with this StructureIdentifier.
751         * @return the {@link PdbId} object
752         * @since 6.0.0
753         */
754        PdbId getPdbId();
755        
756        /**Sets the {@link PdbId} identifier associated with this structure.
757         * @param pdbId the {@link PdbId} identifier object to set
758         * @since 6.0.0
759         */
760        void setPdbId(PdbId pdbId);
761
762}