Merge branch 'develop' into features/filetypeEnum
[jalview.git] / src / MCview / PDBfile.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package MCview;
22
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.DBRefSource;
25 import jalview.datamodel.SequenceI;
26 import jalview.io.DataSourceType;
27 import jalview.io.FileParse;
28 import jalview.io.StructureFile;
29 import jalview.util.MessageManager;
30
31 import java.io.IOException;
32 import java.util.ArrayList;
33 import java.util.Hashtable;
34 import java.util.List;
35 import java.util.Vector;
36
37 public class PDBfile extends StructureFile
38 {
39   private static String CALC_ID_PREFIX = "JalviewPDB";
40
41   public PDBfile(boolean addAlignmentAnnotations,
42           boolean predictSecondaryStructure, boolean externalSecStr)
43   {
44     super();
45     addSettings(addAlignmentAnnotations, predictSecondaryStructure,
46             externalSecStr);
47   }
48
49   public PDBfile(boolean addAlignmentAnnotations, boolean predictSecStr,
50           boolean externalSecStr, String dataObject,
51           DataSourceType sourceType)
52           throws IOException
53   {
54     super(false, dataObject, sourceType);
55     addSettings(addAlignmentAnnotations, predictSecStr, externalSecStr);
56     doParse();
57   }
58
59   public PDBfile(boolean addAlignmentAnnotations, boolean predictSecStr,
60           boolean externalSecStr,
61           FileParse source) throws IOException
62   {
63     super(false, source);
64     addSettings(addAlignmentAnnotations, predictSecStr, externalSecStr);
65     doParse();
66   }
67
68   @Override
69   public String print(SequenceI[] seqs, boolean jvSuffix)
70   {
71     return null;
72   }
73
74   @Override
75   public void parse() throws IOException
76   {
77     setDbRefType(DBRefSource.PDB);
78     // TODO set the filename sensibly - try using data source name.
79     setId(safeName(getDataName()));
80
81     setChains(new Vector<PDBChain>());
82     List<SequenceI> rna = new ArrayList<SequenceI>();
83     List<SequenceI> prot = new ArrayList<SequenceI>();
84     PDBChain tmpchain;
85     String line = null;
86     boolean modelFlag = false;
87     boolean terFlag = false;
88     String lastID = "";
89
90     int indexx = 0;
91     String atomnam = null;
92     try
93     {
94       while ((line = nextLine()) != null)
95       {
96         if (line.indexOf("HEADER") == 0)
97         {
98           if (line.length() > 62)
99           {
100             String tid;
101             if (line.length() > 67)
102             {
103               tid = line.substring(62, 67).trim();
104             }
105             else
106             {
107               tid = line.substring(62).trim();
108             }
109             if (tid.length() > 0)
110             {
111               setId(tid);
112             }
113             continue;
114           }
115         }
116         // Were we to do anything with SEQRES - we start it here
117         if (line.indexOf("SEQRES") == 0)
118         {
119         }
120
121         if (line.indexOf("MODEL") == 0)
122         {
123           modelFlag = true;
124         }
125
126         if (line.indexOf("TER") == 0)
127         {
128           terFlag = true;
129         }
130
131         if (modelFlag && line.indexOf("ENDMDL") == 0)
132         {
133           break;
134         }
135         if (line.indexOf("ATOM") == 0
136                 || (line.indexOf("HETATM") == 0 && !terFlag))
137         {
138           terFlag = false;
139
140           // Jalview is only interested in CA bonds????
141           atomnam = line.substring(12, 15).trim();
142           if (!atomnam.equals("CA") && !atomnam.equals("P"))
143           {
144             continue;
145           }
146
147           Atom tmpatom = new Atom(line);
148           try
149           {
150           tmpchain = findChain(tmpatom.chain);
151             if (tmpatom.resNumIns.trim().equals(lastID))
152             {
153               // phosphorylated protein - seen both CA and P..
154               continue;
155             }
156             tmpchain.atoms.addElement(tmpatom);
157           } catch (Exception e)
158           {
159             tmpchain = new PDBChain(getId(), tmpatom.chain);
160             getChains().add(tmpchain);
161             tmpchain.atoms.addElement(tmpatom);
162           }
163           lastID = tmpatom.resNumIns.trim();
164         }
165         index++;
166       }
167
168       makeResidueList();
169       makeCaBondList();
170
171       if (getId() == null)
172       {
173         setId(inFile.getName());
174       }
175       for (PDBChain chain : getChains())
176       {
177         SequenceI chainseq = postProcessChain(chain);
178         if (isRNA(chainseq))
179         {
180           rna.add(chainseq);
181         }
182         else
183         {
184           prot.add(chainseq);
185         }
186       }
187       if (predictSecondaryStructure)
188       {
189         addSecondaryStructure(rna, prot);
190       }
191     } catch (OutOfMemoryError er)
192     {
193       System.out.println("OUT OF MEMORY LOADING PDB FILE");
194       throw new IOException(
195               MessageManager
196                       .getString("exception.outofmemory_loading_pdb_file"));
197     } catch (NumberFormatException ex)
198     {
199       if (line != null)
200       {
201         System.err.println("Couldn't read number from line:");
202         System.err.println(line);
203       }
204     }
205     markCalcIds();
206   }
207
208
209
210   /**
211    * Process a parsed chain to construct and return a Sequence, and add it to
212    * the list of sequences parsed.
213    * 
214    * @param chain
215    * @return
216    */
217
218   public static boolean isCalcIdHandled(String calcId)
219   {
220     return calcId != null && (CALC_ID_PREFIX.equals(calcId));
221   }
222
223   public static boolean isCalcIdForFile(AlignmentAnnotation alan,
224           String pdbFile)
225   {
226     return alan.getCalcId() != null
227             && CALC_ID_PREFIX.equals(alan.getCalcId())
228             && pdbFile.equals(alan.getProperty("PDBID"));
229   }
230
231   public static String relocateCalcId(String calcId,
232           Hashtable<String, String> alreadyLoadedPDB) throws Exception
233   {
234     int s = CALC_ID_PREFIX.length(), end = calcId
235             .indexOf(CALC_ID_PREFIX, s);
236     String between = calcId.substring(s, end - 1);
237     return CALC_ID_PREFIX + alreadyLoadedPDB.get(between) + ":"
238             + calcId.substring(end);
239   }
240
241   private void markCalcIds()
242   {
243     for (SequenceI sq : seqs)
244     {
245       if (sq.getAnnotation() != null)
246       {
247         for (AlignmentAnnotation aa : sq.getAnnotation())
248         {
249           String oldId = aa.getCalcId();
250           if (oldId == null)
251           {
252             oldId = "";
253           }
254           aa.setCalcId(CALC_ID_PREFIX);
255           aa.setProperty("PDBID", getId());
256           aa.setProperty("oldCalcId", oldId);
257         }
258       }
259     }
260   }
261
262 }