97e11eb05db197b43cb7ce699922e845e76aaf73
[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     sourceDBRef.setStartRes(pdbSequence.getStart());
120     sourceDBRef.setEndRes(pdbSequence.getEnd());
121     pdbSequence.setSourceDBRef(sourceDBRef);
122     pdbSequence.addPDBId(entry);
123     pdbSequence.addDBRef(sourceDBRef);
124     SequenceI chainseq = pdbSequence;
125     seqs.addElement(chainseq);
126     AlignmentAnnotation[] chainannot = chainseq.getAnnotation();
127
128     if (chainannot != null && visibleChainAnnotation)
129     {
130       for (int ai = 0; ai < chainannot.length; ai++)
131       {
132         chainannot[ai].visible = visibleChainAnnotation;
133         annotations.addElement(chainannot[ai]);
134       }
135     }
136     return chainseq;
137   }
138
139   @SuppressWarnings({ "unchecked", "rawtypes" })
140   protected void processPdbFileWithAnnotate3d(List<SequenceI> rna)
141           throws Exception
142   {
143     // System.out.println("this is a PDB format and RNA sequence");
144     // note: we use reflection here so that the applet can compile and run
145     // without the HTTPClient bits and pieces needed for accessing Annotate3D
146     // web service
147     try
148     {
149       Class cl = Class.forName("jalview.ws.jws1.Annotate3D");
150       if (cl != null)
151       {
152         // TODO: use the PDB ID of the structure if one is available, to save
153         // bandwidth and avoid uploading the whole structure to the service
154         Object annotate3d = cl.getConstructor(new Class[] {}).newInstance(
155                 new Object[] {});
156         AlignmentI al = ((AlignmentI) cl.getMethod("getRNAMLFor",
157                 new Class[] { FileParse.class }).invoke(annotate3d,
158                 new Object[] { new FileParse(getDataName(), type) }));
159         for (SequenceI sq : al.getSequences())
160         {
161           if (sq.getDatasetSequence() != null)
162           {
163             if (sq.getDatasetSequence().getAllPDBEntries() != null)
164             {
165               sq.getDatasetSequence().getAllPDBEntries().clear();
166             }
167           }
168           else
169           {
170             if (sq.getAllPDBEntries() != null)
171             {
172               sq.getAllPDBEntries().clear();
173             }
174           }
175         }
176         replaceAndUpdateChains(rna, al, AlignSeq.DNA, false);
177       }
178     } catch (ClassNotFoundException x)
179     {
180       // ignore classnotfounds - occurs in applet
181     }
182   }
183
184   @SuppressWarnings("unchecked")
185   protected void replaceAndUpdateChains(List<SequenceI> prot,
186           AlignmentI al, String pep, boolean b)
187   {
188     List<List<? extends Object>> replaced = AlignSeq
189             .replaceMatchingSeqsWith(seqs, annotations, prot, al, pep,
190                     false);
191     for (PDBChain ch : getChains())
192     {
193       int p = 0;
194       for (SequenceI sq : (List<SequenceI>) replaced.get(0))
195       {
196         p++;
197         if (sq == ch.sequence || sq.getDatasetSequence() == ch.sequence)
198         {
199           p = -p;
200           break;
201         }
202       }
203       if (p < 0)
204       {
205         p = -p - 1;
206         // set shadow entry for chains
207         ch.shadow = (SequenceI) replaced.get(1).get(p);
208         ch.shadowMap = ((AlignSeq) replaced.get(2).get(p))
209                 .getMappingFromS1(false);
210       }
211     }
212   }
213
214   /**
215    * Predict secondary structure for RNA and/or protein sequences and add as
216    * annotations
217    * 
218    * @param rnaSequences
219    * @param proteinSequences
220    */
221   protected void addSecondaryStructure(List<SequenceI> rnaSequences,
222           List<SequenceI> proteinSequences)
223   {
224     /*
225      * Currently using Annotate3D for RNA, but only if the 'use external
226      * prediction' flag is set
227      */
228     if (externalSecondaryStructure && rnaSequences.size() > 0)
229     {
230       try
231       {
232         processPdbFileWithAnnotate3d(rnaSequences);
233       } catch (Exception x)
234       {
235         System.err.println("Exceptions when dealing with RNA in pdb file");
236         x.printStackTrace();
237
238       }
239     }
240
241     /*
242      * Currently using JMol PDB parser for peptide
243      */
244     if (proteinSequences.size() > 0)
245     {
246       try
247       {
248         processWithJmolParser(proteinSequences);
249       } catch (Exception x)
250       {
251         System.err
252                 .println("Exceptions from Jmol when processing data in pdb file");
253         x.printStackTrace();
254       }
255     }
256   }
257
258   @SuppressWarnings({ "unchecked", "rawtypes" })
259   private void processWithJmolParser(List<SequenceI> prot) throws Exception
260   {
261     try
262     {
263
264       Class cl = Class.forName("jalview.ext.jmol.JmolParser");
265       if (cl != null)
266       {
267         final Constructor constructor = cl.getConstructor(new Class[] {
268             boolean.class, boolean.class, boolean.class, FileParse.class });
269         final Object[] args = new Object[] { visibleChainAnnotation,
270             predictSecondaryStructure, externalSecondaryStructure,
271             new FileParse(getDataName(), type) };
272
273         StructureImportSettings.setShowSeqFeatures(false);
274         StructureImportSettings.setVisibleChainAnnotation(false);
275         StructureImportSettings
276                 .setPredictSecondaryStructure(predictSecondaryStructure);
277         StructureImportSettings
278                 .setExternalSecondaryStructure(externalSecondaryStructure);
279         Object jmf = constructor.newInstance(args);
280         AlignmentI al = new Alignment((SequenceI[]) cl.getMethod(
281                 "getSeqsAsArray", new Class[] {}).invoke(jmf));
282         cl.getMethod("addAnnotations", new Class[] { AlignmentI.class })
283                 .invoke(jmf, al);
284         for (SequenceI sq : al.getSequences())
285         {
286           if (sq.getDatasetSequence() != null)
287           {
288             sq.getDatasetSequence().getAllPDBEntries().clear();
289           }
290           else
291           {
292             sq.getAllPDBEntries().clear();
293           }
294         }
295         replaceAndUpdateChains(prot, al, AlignSeq.PEP, false);
296       }
297     } catch (ClassNotFoundException q)
298     {
299     }
300     StructureImportSettings.setShowSeqFeatures(true);
301   }
302
303   public PDBChain findChain(String id) throws Exception
304   {
305     for (PDBChain chain : getChains())
306     {
307       if (chain.id.equals(id))
308       {
309         return chain;
310       }
311     }
312     throw new Exception("PDB chain not Found!");
313   }
314
315   public void makeResidueList()
316   {
317     for (PDBChain chain : getChains())
318     {
319       chain.makeResidueList(visibleChainAnnotation);
320     }
321   }
322
323   public void makeCaBondList()
324   {
325     for (PDBChain chain : getChains())
326     {
327       chain.makeCaBondList();
328     }
329   }
330
331   public void setChargeColours()
332   {
333     for (PDBChain chain : getChains())
334     {
335       chain.setChargeColours();
336     }
337   }
338
339   public void setColours(jalview.schemes.ColourSchemeI cs)
340   {
341     for (PDBChain chain : getChains())
342     {
343       chain.setChainColours(cs);
344     }
345   }
346
347   public void setChainColours()
348   {
349     int i = 0;
350     for (PDBChain chain : getChains())
351     {
352       chain.setChainColours(Color.getHSBColor(1.0f / i++, .4f, 1.0f));
353     }
354   }
355
356   public static boolean isRNA(SequenceI seq)
357   {
358     for (char c : seq.getSequence())
359     {
360       if ((c != 'A') && (c != 'C') && (c != 'G') && (c != 'U'))
361       {
362         return false;
363       }
364     }
365     return true;
366   }
367
368   /**
369    * make a friendly ID string.
370    * 
371    * @param dataName
372    * @return truncated dataName to after last '/'
373    */
374   protected String safeName(String dataName)
375   {
376     int p = 0;
377     while ((p = dataName.indexOf("/")) > -1 && p < dataName.length())
378     {
379       dataName = dataName.substring(p + 1);
380     }
381     return dataName;
382   }
383
384   public String getId()
385   {
386     return id;
387   }
388
389   public void setId(String id)
390   {
391     this.id = id;
392   }
393
394   public Vector<PDBChain> getChains()
395   {
396     return chains;
397   }
398
399   public void setChains(Vector<PDBChain> chains)
400   {
401     this.chains = chains;
402   }
403
404   public String getDbRefType()
405   {
406     return dbRefType;
407   }
408
409   public void setDbRefType(String dbRefType)
410   {
411     this.dbRefType = dbRefType;
412   }
413
414   /**
415    * Returns a descriptor for suitable feature display settings with
416    * <ul>
417    * <li>ResNums or insertions features visible</li>
418    * <li>insertions features coloured red</li>
419    * <li>ResNum features coloured by label</li>
420    * <li>Insertions displayed above (on top of) ResNums</li>
421    * </ul>
422    */
423   @Override
424   public FeatureSettingsModelI getFeatureColourScheme()
425   {
426     return new PDBFeatureSettings();
427   }
428 }