JAL-1919 PDBfile and JmolParser refactor
[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.SequenceI;
25 import jalview.io.FileParse;
26 import jalview.io.StructureFile;
27 import jalview.util.MessageManager;
28
29 import java.io.IOException;
30 import java.util.ArrayList;
31 import java.util.Hashtable;
32 import java.util.List;
33 import java.util.Vector;
34
35 public class PDBfile extends StructureFile
36 {
37   private static String CALC_ID_PREFIX = "JalviewPDB";
38
39   public PDBfile(boolean addAlignmentAnnotations,
40           boolean predictSecondaryStructure, boolean externalSecStr)
41   {
42     super();
43     this.visibleChainAnnotation = addAlignmentAnnotations;
44     this.predictSecondaryStructure = predictSecondaryStructure;
45     this.externalSecondaryStructure = externalSecStr;
46   }
47
48   public PDBfile(boolean addAlignmentAnnotations,
49           boolean predictSecondaryStructure, boolean externalSecStr,
50           String file, String protocol) throws IOException
51   {
52     super(false, file, protocol);
53     this.visibleChainAnnotation = addAlignmentAnnotations;
54     this.predictSecondaryStructure = predictSecondaryStructure;
55     this.externalSecondaryStructure = externalSecStr;
56     doParse();
57   }
58
59   public PDBfile(boolean addAlignmentAnnotations,
60           boolean predictSecondaryStructure, boolean externalSecStr,
61           FileParse source) throws IOException
62   {
63     super(false, source);
64     this.visibleChainAnnotation = addAlignmentAnnotations;
65     this.predictSecondaryStructure = predictSecondaryStructure;
66     this.externalSecondaryStructure = externalSecStr;
67     doParse();
68   }
69
70   @Override
71   public String print()
72   {
73     return null;
74   }
75
76   @Override
77   public void parse() throws IOException
78   {
79     // TODO set the filename sensibly - try using data source name.
80     setId(safeName(getDataName()));
81
82     setChains(new Vector<PDBChain>());
83     List<SequenceI> rna = new ArrayList<SequenceI>();
84     List<SequenceI> prot = new ArrayList<SequenceI>();
85     PDBChain tmpchain;
86     String line = null;
87     boolean modelFlag = false;
88     boolean terFlag = false;
89     String lastID = "";
90
91     int indexx = 0;
92     String atomnam = null;
93     try
94     {
95       while ((line = nextLine()) != null)
96       {
97         if (line.indexOf("HEADER") == 0)
98         {
99           if (line.length() > 62)
100           {
101             String tid;
102             if (line.length() > 67)
103             {
104               tid = line.substring(62, 67).trim();
105             }
106             else
107             {
108               tid = line.substring(62).trim();
109             }
110             if (tid.length() > 0)
111             {
112               setId(tid);
113             }
114             continue;
115           }
116         }
117         // Were we to do anything with SEQRES - we start it here
118         if (line.indexOf("SEQRES") == 0)
119         {
120         }
121
122         if (line.indexOf("MODEL") == 0)
123         {
124           modelFlag = true;
125         }
126
127         if (line.indexOf("TER") == 0)
128         {
129           terFlag = true;
130         }
131
132         if (modelFlag && line.indexOf("ENDMDL") == 0)
133         {
134           break;
135         }
136         if (line.indexOf("ATOM") == 0
137                 || (line.indexOf("HETATM") == 0 && !terFlag))
138         {
139           terFlag = false;
140
141           // Jalview is only interested in CA bonds????
142           atomnam = line.substring(12, 15).trim();
143           if (!atomnam.equals("CA") && !atomnam.equals("P"))
144           {
145             continue;
146           }
147
148           Atom tmpatom = new Atom(line);
149           try
150           {
151           tmpchain = findChain(tmpatom.chain);
152             if (tmpatom.resNumIns.trim().equals(lastID))
153             {
154               // phosphorylated protein - seen both CA and P..
155               continue;
156             }
157             tmpchain.atoms.addElement(tmpatom);
158           } catch (Exception e)
159           {
160             tmpchain = new PDBChain(getId(), tmpatom.chain);
161             getChains().add(tmpchain);
162             tmpchain.atoms.addElement(tmpatom);
163           }
164           lastID = tmpatom.resNumIns.trim();
165         }
166         index++;
167       }
168
169       makeResidueList();
170       makeCaBondList();
171
172       if (getId() == null)
173       {
174         setId(inFile.getName());
175       }
176       for (PDBChain chain : getChains())
177       {
178         SequenceI chainseq = postProcessChain(chain);
179         if (isRNA(chainseq))
180         {
181           rna.add(chainseq);
182         }
183         else
184         {
185           prot.add(chainseq);
186         }
187       }
188       if (predictSecondaryStructure)
189       {
190         addSecondaryStructure(rna, prot);
191       }
192     } catch (OutOfMemoryError er)
193     {
194       System.out.println("OUT OF MEMORY LOADING PDB FILE");
195       throw new IOException(
196               MessageManager
197                       .getString("exception.outofmemory_loading_pdb_file"));
198     } catch (NumberFormatException ex)
199     {
200       if (line != null)
201       {
202         System.err.println("Couldn't read number from line:");
203         System.err.println(line);
204       }
205     }
206     markCalcIds();
207   }
208
209
210
211   /**
212    * Process a parsed chain to construct and return a Sequence, and add it to
213    * the list of sequences parsed.
214    * 
215    * @param chain
216    * @return
217    */
218
219   public static boolean isCalcIdHandled(String calcId)
220   {
221     return calcId != null && (CALC_ID_PREFIX.equals(calcId));
222   }
223
224   public static boolean isCalcIdForFile(AlignmentAnnotation alan,
225           String pdbFile)
226   {
227     return alan.getCalcId() != null
228             && CALC_ID_PREFIX.equals(alan.getCalcId())
229             && pdbFile.equals(alan.getProperty("PDBID"));
230   }
231
232   public static String relocateCalcId(String calcId,
233           Hashtable<String, String> alreadyLoadedPDB) throws Exception
234   {
235     int s = CALC_ID_PREFIX.length(), end = calcId
236             .indexOf(CALC_ID_PREFIX, s);
237     String between = calcId.substring(s, end - 1);
238     return CALC_ID_PREFIX + alreadyLoadedPDB.get(between) + ":"
239             + calcId.substring(end);
240   }
241
242   private void markCalcIds()
243   {
244     for (SequenceI sq : seqs)
245     {
246       if (sq.getAnnotation() != null)
247       {
248         for (AlignmentAnnotation aa : sq.getAnnotation())
249         {
250           String oldId = aa.getCalcId();
251           if (oldId == null)
252           {
253             oldId = "";
254           }
255           aa.setCalcId(CALC_ID_PREFIX);
256           aa.setProperty("PDBID", getId());
257           aa.setProperty("oldCalcId", oldId);
258         }
259       }
260     }
261   }
262
263 }