4fc88141cff64812809c1c38911fb422a269d79a
[jalview.git] / src / MCview / PDBfile.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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 java.io.*;
24 import java.util.*;
25
26 import java.awt.*;
27
28 import jalview.analysis.AlignSeq;
29 import jalview.datamodel.*;
30 import jalview.io.FileParse;
31
32 public class PDBfile extends jalview.io.AlignFile
33 {
34   public Vector chains;
35
36   public String id;
37
38   /**
39    * set to true to add chain alignment annotation as visible annotation.
40    */
41   boolean VisibleChainAnnotation = false;
42
43   public PDBfile(String inFile, String inType) throws IOException
44   {
45     super(inFile, inType);
46   }
47
48   public PDBfile(FileParse source) throws IOException
49   {
50     super(source);
51   }
52
53   public String print()
54   {
55     return null;
56   }
57
58   public void parse() throws IOException
59   {
60     // TODO set the filename sensibly - try using data source name.
61     id = safeName(getDataName());
62
63     chains = new Vector();
64     ArrayList<SequenceI> rna=new ArrayList<SequenceI>(), prot=new ArrayList<SequenceI>();
65     PDBChain tmpchain;
66     String line = null;
67     boolean modelFlag = false;
68     boolean terFlag = false;
69     String lastID = "";
70
71     int index = 0;
72     String atomnam = null;
73     try
74     {
75       while ((line = nextLine()) != null)
76       {
77         if (line.indexOf("HEADER") == 0)
78         {
79           if (line.length() > 62)
80           {
81             String tid;
82             if (line.length() > 67)
83             {
84               tid = line.substring(62, 67).trim();
85             }
86             else
87             {
88               tid = line.substring(62).trim();
89             }
90             if (tid.length() > 0)
91             {
92               id = tid;
93             }
94             continue;
95           }
96         }
97         // Were we to do anything with SEQRES - we start it here
98         if (line.indexOf("SEQRES") == 0)
99         {
100         }
101
102         if (line.indexOf("MODEL") == 0)
103         {
104           modelFlag = true;
105         }
106
107         if (line.indexOf("TER") == 0)
108         {
109           terFlag = true;
110         }
111
112         if (modelFlag && line.indexOf("ENDMDL") == 0)
113         {
114           break;
115         }
116         if (line.indexOf("ATOM") == 0
117                 || (line.indexOf("HETATM") == 0 && !terFlag))
118         {
119           terFlag = false;
120
121           // Jalview is only interested in CA bonds????
122           atomnam = line.substring(12, 15).trim();
123           if (!atomnam.equals("CA") && !atomnam.equals("P"))
124           {
125             continue;
126           }
127
128           Atom tmpatom = new Atom(line);
129           tmpchain = findChain(tmpatom.chain);
130           if (tmpchain != null)
131           {
132             if (tmpatom.resNumIns.trim().equals(lastID))
133             {
134               // phosphorylated protein - seen both CA and P..
135               continue;
136             }
137             tmpchain.atoms.addElement(tmpatom);
138           }
139           else
140           {
141             tmpchain = new PDBChain(id, tmpatom.chain);
142             chains.addElement(tmpchain);
143             tmpchain.atoms.addElement(tmpatom);
144           }
145           lastID = tmpatom.resNumIns.trim();
146         }
147         index++;
148       }
149
150       makeResidueList();
151       makeCaBondList();
152
153       if (id == null)
154       {
155         id = inFile.getName();
156       }
157       for (int i = 0; i < chains.size(); i++)
158       {
159         SequenceI dataset = ((PDBChain) chains.elementAt(i)).sequence;
160         dataset.setName(id + "|" + dataset.getName());
161         PDBEntry entry = new PDBEntry();
162         entry.setId(id);
163         entry.setProperty(new Hashtable());
164         if (((PDBChain)chains.elementAt(i)).id!=null) {
165           entry.getProperty().put("CHAIN", ((PDBChain)chains.elementAt(i)).id);
166         }
167         if (inFile != null)
168         {
169           entry.setFile(inFile.getAbsolutePath());
170         }
171         else
172         {
173           // TODO: decide if we should dump the datasource to disk
174           entry.setFile(getDataName());
175         }
176         dataset.addPDBId(entry);
177         SequenceI chainseq = dataset.deriveSequence(); // PDBChain objects
178         // maintain reference to
179         // dataset
180         seqs.addElement(chainseq);
181        if(isRNA(chainseq)==true)
182        {
183          rna.add(chainseq);
184        } else {
185          prot.add(chainseq);
186        }
187          
188         AlignmentAnnotation[] chainannot = chainseq.getAnnotation();
189         
190         if (chainannot != null)
191         {
192           for (int ai = 0; ai < chainannot.length; ai++)
193           {
194         
195             chainannot[ai].visible = VisibleChainAnnotation;
196             annotations.addElement(chainannot[ai]);
197           }
198         }
199       }
200       if (rna.size()>0)
201       try {
202         processPdbFileWithAnnotate3d(rna);
203       } catch (Exception x)
204       {
205         System.err.println("Exceptions when dealing with RNA in pdb file");
206         x.printStackTrace();
207         
208       };
209       if (prot.size()>0)
210       try {
211         processPdbFileWithJmol(prot);
212       } catch (Exception x)
213       {
214         System.err.println("Exceptions when dealing with RNA in pdb file");
215         x.printStackTrace();
216         
217       };
218       if (prot.size()>0)
219       try {
220         processPdbFileWithJmol(prot);
221       } catch (Exception x)
222       {
223         System.err.println("Exceptions when dealing with RNA in pdb file");
224         x.printStackTrace();
225         
226       };
227     } catch (OutOfMemoryError er)
228     {
229       System.out.println("OUT OF MEMORY LOADING PDB FILE");
230       throw new IOException("Out of memory loading PDB File");
231     } catch (NumberFormatException ex)
232     {
233       if (line != null)
234       {
235         System.err.println("Couldn't read number from line:");
236         System.err.println(line);
237       }
238     }
239   }
240   private void processPdbFileWithJmol(ArrayList<SequenceI> prot) throws Exception
241   {
242     try {
243       Class cl = Class.forName("jalview.ext.jmol.PDBFileWithJmol");
244       if (cl!=null)
245       {
246         Object jmf = cl.getConstructor(new Class[] {FileParse.class}).newInstance(new Object[] {new FileParse(getDataName(),type)});
247         Alignment al = new Alignment((SequenceI[]) cl.getMethod("getSeqsAsArray", new Class[] {}).invoke(jmf));
248         cl.getMethod("addAnnotations",new Class[] {Alignment.class}).invoke(jmf, al);
249         replaceMatchingSeqsWith(prot, al, AlignSeq.PEP);
250       }
251     } catch (ClassNotFoundException q)
252     {}
253   }
254   private void processPdbFileWithAnnotate3d(ArrayList<SequenceI> rna) throws Exception {
255 //    System.out.println("this is a PDB format and RNA sequence");
256     // note: we use reflection here so that the applet can compile and run without the HTTPClient bits and pieces needed for accessing Annotate3D web service
257     try {
258     Class cl = Class.forName("jalview.ws.jws1.Annotate3D");
259     if (cl!=null)
260     {
261       // TODO: use the PDB ID of the structure if one is available, to save bandwidth and avoid uploading the whole structure to the service
262       Object annotate3d = cl.getConstructor(new Class[] {}).newInstance(new Object[] {});
263       AlignmentI al = ((AlignmentI) cl.getMethod("getRNAMLFor", new Class[] { FileParse.class}).invoke(annotate3d, new Object[] { new FileParse(getDataName(),type)}));
264       replaceMatchingSeqsWith(rna, al, AlignSeq.DNA);
265     }
266     } catch (ClassNotFoundException x)
267     {
268       //ignore classnotfounds - occurs in applet
269     };
270   }
271   private void replaceMatchingSeqsWith(ArrayList<SequenceI> ochains, AlignmentI al, String dnaOrProtein)
272   {
273     if (al!=null && al.getHeight()>0)
274     {
275       ArrayList<SequenceI> matches=new ArrayList<SequenceI>();
276       ArrayList<AlignSeq> aligns=new ArrayList<AlignSeq>();
277       
278       for (SequenceI sq:ochains)
279       {
280         SequenceI bestm=null;
281         AlignSeq bestaseq=null;
282         int bestscore=0;
283         for (SequenceI msq:al.getSequences())
284         {
285           AlignSeq aseq = AlignSeq.doGlobalNWAlignment(msq, sq, dnaOrProtein);
286           if (bestm==null || aseq.getMaxScore()>bestscore)
287           {
288             bestscore=aseq.getMaxScore();
289             bestaseq= aseq;
290             bestm=msq;
291           }
292         }
293         System.out.println("Best Score for "+(matches.size()+1)+" :"+bestscore);
294         matches.add(bestm);
295         aligns.add(bestaseq);
296         al.deleteSequence(bestm);
297       }
298       for (int p=0,pSize=seqs.size();p<pSize;p++)
299       {
300         SequenceI sq,sp=seqs.get(p);
301         int q;
302         if ((q=ochains.indexOf(sp))>-1)
303         {
304           seqs.set(p, sq=matches.get(q));
305           sq.setName(sp.getName());
306           sq.setDescription(sp.getDescription());
307           sq.transferAnnotation(sp, aligns.get(q).getMappingFromS1(false));
308           int inspos=-1;
309           for (int ap=0;ap<annotations.size();)
310           {
311             if (((AlignmentAnnotation)annotations.get(ap)).sequenceRef==sp) {
312               if (inspos==-1)
313               {
314                 inspos=ap;
315               }
316               annotations.remove(ap);
317             } else {
318               ap++;
319             }
320           }
321           if (sq.getAnnotation()!=null) {
322             annotations.addAll(inspos, Arrays.asList(sq.getAnnotation()));
323           }
324         }
325       }
326     }
327   }
328   /**
329    * make a friendly ID string.
330    * 
331    * @param dataName
332    * @return truncated dataName to after last '/'
333    */
334   private String safeName(String dataName)
335   {
336     int p = 0;
337     while ((p = dataName.indexOf("/")) > -1 && p < dataName.length())
338     {
339       dataName = dataName.substring(p + 1);
340     }
341     return dataName;
342   }
343
344   public void makeResidueList()
345   {
346     for (int i = 0; i < chains.size(); i++)
347     {
348       ((PDBChain) chains.elementAt(i)).makeResidueList();
349     }
350   }
351
352   public void makeCaBondList()
353   {
354     for (int i = 0; i < chains.size(); i++)
355     {
356       ((PDBChain) chains.elementAt(i)).makeCaBondList();
357     }
358   }
359
360   public PDBChain findChain(String id)
361   {
362     for (int i = 0; i < chains.size(); i++)
363     {
364       if (((PDBChain) chains.elementAt(i)).id.equals(id))
365       {
366         return (PDBChain) chains.elementAt(i);
367       }
368     }
369
370     return null;
371   }
372
373   public void setChargeColours()
374   {
375     for (int i = 0; i < chains.size(); i++)
376     {
377       ((PDBChain) chains.elementAt(i)).setChargeColours();
378     }
379   }
380
381   public void setColours(jalview.schemes.ColourSchemeI cs)
382   {
383     for (int i = 0; i < chains.size(); i++)
384     {
385       ((PDBChain) chains.elementAt(i)).setChainColours(cs);
386     }
387   }
388
389   public void setChainColours()
390   {
391     for (int i = 0; i < chains.size(); i++)
392     {
393       ((PDBChain) chains.elementAt(i)).setChainColours(Color.getHSBColor(
394               1.0f / (float) i, .4f, 1.0f));
395     }
396   }
397   public boolean isRNA(SequenceI seqs)
398   {
399           for (int i=0;i<seqs.getLength();i++){
400                   if((seqs.getCharAt(i)!='A') &&(seqs.getCharAt(i)!='C')&&(seqs.getCharAt(i)!='G')&&(seqs.getCharAt(i)!='U'))
401                   {
402                           return false;
403                   }
404           }
405          
406                   return true;
407           
408           
409   }
410 }