JAL-1926 JAL-2106 remove startRes/endRes fields - not used
[jalview.git] / src / jalview / io / StructureFile.java
1 package jalview.io;
2
3 import jalview.analysis.AlignSeq;
4 import jalview.api.FeatureSettingsModelI;
5 import jalview.datamodel.Alignment;
6 import jalview.datamodel.AlignmentAnnotation;
7 import jalview.datamodel.AlignmentI;
8 import jalview.datamodel.DBRefEntry;
9 import jalview.datamodel.DBRefSource;
10 import jalview.datamodel.PDBEntry;
11 import jalview.datamodel.SequenceI;
12 import jalview.structure.StructureImportSettings;
13
14 import java.awt.Color;
15 import java.io.IOException;
16 import java.lang.reflect.Constructor;
17 import java.util.Hashtable;
18 import java.util.List;
19 import java.util.Vector;
20
21 import MCview.PDBChain;
22
23 public abstract class StructureFile extends AlignFile
24 {
25
26   private String id;
27
28   private String dbRefType;
29
30   /**
31    * set to true to add derived sequence annotations (temp factor read from
32    * file, or computed secondary structure) to the alignment
33    */
34   protected boolean visibleChainAnnotation = false;
35
36   /**
37    * Set true to predict secondary structure (using JMol for protein, Annotate3D
38    * for RNA)
39    */
40   protected boolean predictSecondaryStructure = false;
41
42   /**
43    * Set true (with predictSecondaryStructure=true) to predict secondary
44    * structure using an external service (currently Annotate3D for RNA only)
45    */
46   protected boolean externalSecondaryStructure = false;
47
48   private Vector<PDBChain> chains;
49
50   public StructureFile(String inFile, String type) throws IOException
51   {
52     super(inFile, type);
53   }
54
55   public StructureFile(FileParse fp) throws IOException
56   {
57     super(fp);
58   }
59
60   public void addSettings(boolean addAlignmentAnnotations,
61           boolean predictSecondaryStructure, boolean externalSecStr)
62   {
63     this.visibleChainAnnotation = addAlignmentAnnotations;
64     this.predictSecondaryStructure = predictSecondaryStructure;
65     this.externalSecondaryStructure = externalSecStr;
66   }
67
68   public void xferSettings()
69   {
70     this.visibleChainAnnotation = StructureImportSettings
71             .isVisibleChainAnnotation();
72     this.predictSecondaryStructure = StructureImportSettings
73             .isPredictSecondaryStructure();
74     this.externalSecondaryStructure = StructureImportSettings
75             .isExternalSecondaryStructure();
76
77   }
78
79   public StructureFile(boolean parseImmediately, String dataObject, String type)
80           throws IOException
81   {
82     super(parseImmediately, dataObject, type);
83   }
84
85   public StructureFile(boolean a, FileParse fp) throws IOException
86   {
87     super(a, fp);
88   }
89
90   public StructureFile()
91   {
92   }
93
94   @SuppressWarnings("rawtypes")
95   protected SequenceI postProcessChain(PDBChain chain)
96   {
97     SequenceI pdbSequence = chain.sequence;
98     pdbSequence.setName(getId() + "|" + pdbSequence.getName());
99     PDBEntry entry = new PDBEntry();
100     entry.setId(getId());
101     entry.setType(this.dbRefType);
102     entry.setProperty(new Hashtable());
103     if (chain.id != null)
104     {
105       entry.setChainCode(String.valueOf(chain.id));
106     }
107     if (inFile != null)
108     {
109       entry.setFile(inFile.getAbsolutePath());
110     }
111     else
112     {
113       entry.setFile(getDataName());
114     }
115
116     DBRefEntry sourceDBRef = new DBRefEntry();
117     sourceDBRef.setAccessionId(getId());
118     sourceDBRef.setSource(DBRefSource.PDB);
119     pdbSequence.setSourceDBRef(sourceDBRef);
120     pdbSequence.addPDBId(entry);
121     pdbSequence.addDBRef(sourceDBRef);
122     SequenceI chainseq = pdbSequence;
123     seqs.addElement(chainseq);
124     AlignmentAnnotation[] chainannot = chainseq.getAnnotation();
125
126     if (chainannot != null && visibleChainAnnotation)
127     {
128       for (int ai = 0; ai < chainannot.length; ai++)
129       {
130         chainannot[ai].visible = visibleChainAnnotation;
131         annotations.addElement(chainannot[ai]);
132       }
133     }
134     return chainseq;
135   }
136
137   @SuppressWarnings({ "unchecked", "rawtypes" })
138   protected void processPdbFileWithAnnotate3d(List<SequenceI> rna)
139           throws Exception
140   {
141     // System.out.println("this is a PDB format and RNA sequence");
142     // note: we use reflection here so that the applet can compile and run
143     // without the HTTPClient bits and pieces needed for accessing Annotate3D
144     // web service
145     try
146     {
147       Class cl = Class.forName("jalview.ws.jws1.Annotate3D");
148       if (cl != null)
149       {
150         // TODO: use the PDB ID of the structure if one is available, to save
151         // bandwidth and avoid uploading the whole structure to the service
152         Object annotate3d = cl.getConstructor(new Class[] {}).newInstance(
153                 new Object[] {});
154         AlignmentI al = ((AlignmentI) cl.getMethod("getRNAMLFor",
155                 new Class[] { FileParse.class }).invoke(annotate3d,
156                 new Object[] { new FileParse(getDataName(), type) }));
157         for (SequenceI sq : al.getSequences())
158         {
159           if (sq.getDatasetSequence() != null)
160           {
161             if (sq.getDatasetSequence().getAllPDBEntries() != null)
162             {
163               sq.getDatasetSequence().getAllPDBEntries().clear();
164             }
165           }
166           else
167           {
168             if (sq.getAllPDBEntries() != null)
169             {
170               sq.getAllPDBEntries().clear();
171             }
172           }
173         }
174         replaceAndUpdateChains(rna, al, AlignSeq.DNA, false);
175       }
176     } catch (ClassNotFoundException x)
177     {
178       // ignore classnotfounds - occurs in applet
179     }
180   }
181
182   @SuppressWarnings("unchecked")
183   protected void replaceAndUpdateChains(List<SequenceI> prot,
184           AlignmentI al, String pep, boolean b)
185   {
186     List<List<? extends Object>> replaced = AlignSeq
187             .replaceMatchingSeqsWith(seqs, annotations, prot, al, pep,
188                     false);
189     for (PDBChain ch : getChains())
190     {
191       int p = 0;
192       for (SequenceI sq : (List<SequenceI>) replaced.get(0))
193       {
194         p++;
195         if (sq == ch.sequence || sq.getDatasetSequence() == ch.sequence)
196         {
197           p = -p;
198           break;
199         }
200       }
201       if (p < 0)
202       {
203         p = -p - 1;
204         // set shadow entry for chains
205         ch.shadow = (SequenceI) replaced.get(1).get(p);
206         ch.shadowMap = ((AlignSeq) replaced.get(2).get(p))
207                 .getMappingFromS1(false);
208       }
209     }
210   }
211
212   /**
213    * Predict secondary structure for RNA and/or protein sequences and add as
214    * annotations
215    * 
216    * @param rnaSequences
217    * @param proteinSequences
218    */
219   protected void addSecondaryStructure(List<SequenceI> rnaSequences,
220           List<SequenceI> proteinSequences)
221   {
222     /*
223      * Currently using Annotate3D for RNA, but only if the 'use external
224      * prediction' flag is set
225      */
226     if (externalSecondaryStructure && rnaSequences.size() > 0)
227     {
228       try
229       {
230         processPdbFileWithAnnotate3d(rnaSequences);
231       } catch (Exception x)
232       {
233         System.err.println("Exceptions when dealing with RNA in pdb file");
234         x.printStackTrace();
235
236       }
237     }
238
239     /*
240      * Currently using JMol PDB parser for peptide
241      */
242     if (proteinSequences.size() > 0)
243     {
244       try
245       {
246         processWithJmolParser(proteinSequences);
247       } catch (Exception x)
248       {
249         System.err
250                 .println("Exceptions from Jmol when processing data in pdb file");
251         x.printStackTrace();
252       }
253     }
254   }
255
256   @SuppressWarnings({ "unchecked", "rawtypes" })
257   private void processWithJmolParser(List<SequenceI> prot) throws Exception
258   {
259     try
260     {
261
262       Class cl = Class.forName("jalview.ext.jmol.JmolParser");
263       if (cl != null)
264       {
265         final Constructor constructor = cl.getConstructor(new Class[] {
266             boolean.class, boolean.class, boolean.class, FileParse.class });
267         final Object[] args = new Object[] { visibleChainAnnotation,
268             predictSecondaryStructure, externalSecondaryStructure,
269             new FileParse(getDataName(), type) };
270
271         StructureImportSettings.setShowSeqFeatures(false);
272         StructureImportSettings.setVisibleChainAnnotation(false);
273         StructureImportSettings
274                 .setPredictSecondaryStructure(predictSecondaryStructure);
275         StructureImportSettings
276                 .setExternalSecondaryStructure(externalSecondaryStructure);
277         Object jmf = constructor.newInstance(args);
278         AlignmentI al = new Alignment((SequenceI[]) cl.getMethod(
279                 "getSeqsAsArray", new Class[] {}).invoke(jmf));
280         cl.getMethod("addAnnotations", new Class[] { AlignmentI.class })
281                 .invoke(jmf, al);
282         for (SequenceI sq : al.getSequences())
283         {
284           if (sq.getDatasetSequence() != null)
285           {
286             sq.getDatasetSequence().getAllPDBEntries().clear();
287           }
288           else
289           {
290             sq.getAllPDBEntries().clear();
291           }
292         }
293         replaceAndUpdateChains(prot, al, AlignSeq.PEP, false);
294       }
295     } catch (ClassNotFoundException q)
296     {
297     }
298     StructureImportSettings.setShowSeqFeatures(true);
299   }
300
301   public PDBChain findChain(String id) throws Exception
302   {
303     for (PDBChain chain : getChains())
304     {
305       if (chain.id.equals(id))
306       {
307         return chain;
308       }
309     }
310     throw new Exception("PDB chain not Found!");
311   }
312
313   public void makeResidueList()
314   {
315     for (PDBChain chain : getChains())
316     {
317       chain.makeResidueList(visibleChainAnnotation);
318     }
319   }
320
321   public void makeCaBondList()
322   {
323     for (PDBChain chain : getChains())
324     {
325       chain.makeCaBondList();
326     }
327   }
328
329   public void setChargeColours()
330   {
331     for (PDBChain chain : getChains())
332     {
333       chain.setChargeColours();
334     }
335   }
336
337   public void setColours(jalview.schemes.ColourSchemeI cs)
338   {
339     for (PDBChain chain : getChains())
340     {
341       chain.setChainColours(cs);
342     }
343   }
344
345   public void setChainColours()
346   {
347     int i = 0;
348     for (PDBChain chain : getChains())
349     {
350       chain.setChainColours(Color.getHSBColor(1.0f / i++, .4f, 1.0f));
351     }
352   }
353
354   public static boolean isRNA(SequenceI seq)
355   {
356     for (char c : seq.getSequence())
357     {
358       if ((c != 'A') && (c != 'C') && (c != 'G') && (c != 'U'))
359       {
360         return false;
361       }
362     }
363     return true;
364   }
365
366   /**
367    * make a friendly ID string.
368    * 
369    * @param dataName
370    * @return truncated dataName to after last '/'
371    */
372   protected String safeName(String dataName)
373   {
374     int p = 0;
375     while ((p = dataName.indexOf("/")) > -1 && p < dataName.length())
376     {
377       dataName = dataName.substring(p + 1);
378     }
379     return dataName;
380   }
381
382   public String getId()
383   {
384     return id;
385   }
386
387   public void setId(String id)
388   {
389     this.id = id;
390   }
391
392   public Vector<PDBChain> getChains()
393   {
394     return chains;
395   }
396
397   public void setChains(Vector<PDBChain> chains)
398   {
399     this.chains = chains;
400   }
401
402   public String getDbRefType()
403   {
404     return dbRefType;
405   }
406
407   public void setDbRefType(String dbRefType)
408   {
409     this.dbRefType = dbRefType;
410   }
411
412   /**
413    * Returns a descriptor for suitable feature display settings with
414    * <ul>
415    * <li>ResNums or insertions features visible</li>
416    * <li>insertions features coloured red</li>
417    * <li>ResNum features coloured by label</li>
418    * <li>Insertions displayed above (on top of) ResNums</li>
419    * </ul>
420    */
421   @Override
422   public FeatureSettingsModelI getFeatureColourScheme()
423   {
424     return new PDBFeatureSettings();
425   }
426 }