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