JAL-2136 JAL-2137 Improvements: enable STRUCTMODEL annotation statement to be less...
[jalview.git] / src / jalview / ws / phyre2 / Phyre2Client.java
1 package jalview.ws.phyre2;
2
3 import jalview.datamodel.AlignmentI;
4 import jalview.datamodel.SequenceI;
5 import jalview.fts.core.DecimalFormatTableCellRenderer;
6 import jalview.io.AppletFormatAdapter;
7 import jalview.io.DataSourceType;
8 import jalview.io.FileFormat;
9 import jalview.io.FormatAdapter;
10 import jalview.io.StructureFile;
11 import jalview.schemes.ResidueProperties;
12 import jalview.structure.StructureMapping;
13 import jalview.structure.StructureMappingClient;
14 import jalview.structures.models.MappingOutputModel;
15 import jalview.util.Comparison;
16 import jalview.util.Format;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileReader;
21 import java.io.IOException;
22 import java.io.PrintStream;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26
27 import javax.swing.JTable;
28 import javax.swing.table.DefaultTableModel;
29
30 public class Phyre2Client extends StructureMappingClient
31 {
32   private final static String NEWLINE = System.lineSeparator();
33
34   public static final int UNASSIGNED = -1;
35
36   private final static String PATH_SEPARATOR = File.separator;
37
38   private String fastaMappingFile;
39
40   public Phyre2Client(StructureFile structureFile)
41   {
42     this.structureFile = structureFile;
43   }
44
45   public StructureMapping getStructureMapping(SequenceI seq,
46           String pdbFile, String fMappingFile, String chain)
47   {
48     this.fastaMappingFile = fMappingFile;
49     return getStructureMapping(seq, pdbFile, chain);
50   }
51
52   @Override
53   public StructureMapping getStructureMapping(SequenceI seq,
54           String pdbFile, String chain)
55   {
56     final StringBuilder mappingDetails = new StringBuilder(128);
57     PrintStream ps = new PrintStream(System.out)
58     {
59       @Override
60       public void print(String x)
61       {
62         mappingDetails.append(x);
63       }
64
65       @Override
66       public void println()
67       {
68         mappingDetails.append(NEWLINE);
69       }
70     };
71     HashMap<Integer, int[]> mapping = getPhyre2FastaMapping(seq, ps);
72
73     String mappingOutput = mappingDetails.toString();
74     StructureMapping phyre2ModelMapping = new StructureMapping(seq,
75             pdbFile, structureFile.getId(), chain, mapping, mappingOutput);
76     return phyre2ModelMapping;
77   }
78
79   public HashMap<Integer, int[]> getPhyre2FastaMapping(SequenceI inputSeq,
80           java.io.PrintStream os)
81   {
82     HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
83     AlignmentI seq2Phyre2ModelFastaMapping = null;
84     try
85     {
86       String fastaFile = getFastaMappingFile();
87       DataSourceType protocol = AppletFormatAdapter
88               .checkProtocol(fastaFile);
89       seq2Phyre2ModelFastaMapping = new FormatAdapter().readFile(fastaFile,
90               protocol, FileFormat.Fasta);
91     } catch (IOException e1)
92     {
93       e1.printStackTrace();
94     }
95     SequenceI[] seqs = seq2Phyre2ModelFastaMapping.getSequencesArray();
96     SequenceI tSequenceRes = seqs[0];
97     SequenceI tStructureRes = seqs[1];
98
99     // Essential to resolve fastaAlignment to input sequence and model sequence
100     // coordinates
101     tSequenceRes.setStart(inputSeq.getStart());
102     tSequenceRes.setEnd(inputSeq.getEnd());
103
104     tStructureRes.setStart(structureFile.getSeqsAsArray()[0].getStart());
105     tStructureRes.setEnd(structureFile.getSeqsAsArray()[0].getEnd());
106     try
107     {
108       int sequenceResLenght = tSequenceRes.getLength();
109       int structureResLenght = tStructureRes.getLength();
110       if (sequenceResLenght == structureResLenght)
111       {
112         int prevStructResNum = -1;
113         int alignmentLenght = sequenceResLenght + tSequenceRes.getStart();
114         for (int x = 0; x < alignmentLenght; x++)
115         {
116           int alignSeqResidueIndex = tSequenceRes.findIndex(x);
117           int structResNum = tStructureRes
118                   .findPosition(alignSeqResidueIndex);
119           int sequenceResNum = tSequenceRes
120                   .findPosition(alignSeqResidueIndex - 1);
121           boolean sameResNum = (structResNum == prevStructResNum);
122           // System.out.println(sequenceResNum + " : "
123           // + (sameResNum ? -1 : prevStructResNum));
124           mapping.put(sequenceResNum, new int[] {
125               sameResNum ? -1 : prevStructResNum, -1 });
126           prevStructResNum = structResNum;
127         }
128       }
129     } catch (Exception e)
130     {
131       e.printStackTrace();
132     }
133
134     try
135     {
136       populateAtomPositions(" ", mapping);
137     } catch (IllegalArgumentException e)
138     {
139       e.printStackTrace();
140     } catch (StructureMappingException e)
141     {
142       e.printStackTrace();
143     }
144
145     if (os != null)
146     {
147       MappingOutputModel mop = new MappingOutputModel();
148       mop.setSeqStart(tSequenceRes.getStart());
149       mop.setSeqEnd(tSequenceRes.getEnd());
150       mop.setSeqName(tSequenceRes.getName());
151       mop.setSeqResidue(tSequenceRes.getSequenceAsString());
152
153       mop.setStrStart(tStructureRes.getStart());
154       mop.setStrEnd(tStructureRes.getEnd());
155       mop.setStrName(tStructureRes.getName());
156       mop.setStrResidue(tStructureRes.getSequenceAsString());
157
158       mop.setType("pep");
159       try
160       {
161         os.print(getMappingOutput(mop).toString());
162       } catch (Exception e)
163       {
164         e.printStackTrace();
165       }
166       os.println();
167     }
168     return mapping;
169   }
170
171   private String getFastaMappingFile()
172   {
173     return fastaMappingFile;
174   }
175
176   @Override
177   public StringBuffer getMappingOutput(MappingOutputModel mp)
178           throws StructureMappingException
179   {
180     String seqRes = mp.getSeqResidue();
181     String seqName = mp.getSeqName();
182     int sStart = mp.getSeqStart();
183     int sEnd = mp.getSeqEnd();
184
185     String strRes = mp.getStrResidue();
186     String strName = mp.getStrName();
187     int pdbStart = mp.getStrStart();
188     int pdbEnd = mp.getStrEnd();
189
190     String type = mp.getType();
191
192     int maxid = (seqName.length() >= strName.length()) ? seqName.length()
193             : strName.length();
194     int len = 72 - maxid - 1;
195
196     int nochunks = ((seqRes.length()) / len)
197             + ((seqRes.length()) % len > 0 ? 1 : 0);
198     // output mappings
199     StringBuffer output = new StringBuffer();
200     output.append(NEWLINE);
201     output.append("Sequence \u27f7 Structure mapping details").append(
202             NEWLINE);
203     output.append("Method: Phyre2 Alignment");
204     output.append(NEWLINE).append(NEWLINE);
205
206     output.append(new Format("%" + maxid + "s").form(seqName));
207     output.append(" :  ");
208     output.append(String.valueOf(sStart));
209     output.append(" - ");
210     output.append(String.valueOf(sEnd));
211     output.append(" Maps to ");
212     output.append(NEWLINE);
213     output.append(new Format("%" + maxid + "s").form(strName));
214     output.append(" :  ");
215     output.append(String.valueOf(pdbStart));
216     output.append(" - ");
217     output.append(String.valueOf(pdbEnd));
218     output.append(NEWLINE).append(NEWLINE);
219
220     int matchedSeqCount = 0;
221     for (int j = 0; j < nochunks; j++)
222     {
223       // Print the first aligned sequence
224       output.append(new Format("%" + (maxid) + "s").form(seqName)).append(
225               " ");
226
227       for (int i = 0; i < len; i++)
228       {
229         if ((i + (j * len)) < seqRes.length())
230         {
231           output.append(seqRes.charAt(i + (j * len)));
232         }
233       }
234
235       output.append(NEWLINE);
236       output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
237
238       // Print out the matching chars
239       for (int i = 0; i < len; i++)
240       {
241         try
242         {
243           if ((i + (j * len)) < seqRes.length())
244           {
245             boolean sameChar = Comparison.isSameResidue(
246                     seqRes.charAt(i + (j * len)),
247                     strRes.charAt(i + (j * len)), false);
248             if (sameChar
249                     && !jalview.util.Comparison.isGap(seqRes.charAt(i
250                             + (j * len))))
251             {
252               matchedSeqCount++;
253               output.append("|");
254             }
255             else if (type.equals("pep"))
256             {
257               if (ResidueProperties.getPAM250(seqRes.charAt(i + (j * len)),
258                       strRes.charAt(i + (j * len))) > 0)
259               {
260                 output.append(".");
261               }
262               else
263               {
264                 output.append(" ");
265               }
266             }
267             else
268             {
269               output.append(" ");
270             }
271           }
272         } catch (IndexOutOfBoundsException e)
273         {
274           continue;
275         }
276       }
277       // Now print the second aligned sequence
278       output = output.append(NEWLINE);
279       output = output.append(new Format("%" + (maxid) + "s").form(strName))
280               .append(" ");
281       for (int i = 0; i < len; i++)
282       {
283         if ((i + (j * len)) < strRes.length())
284         {
285           output.append(strRes.charAt(i + (j * len)));
286         }
287       }
288       output.append(NEWLINE).append(NEWLINE);
289     }
290     float pid = (float) matchedSeqCount / seqRes.length() * 100;
291     output.append("Length of alignment = " + seqRes.length()).append(
292             NEWLINE);
293     output.append(new Format("Percentage ID = %2.2f").form(pid));
294     return output;
295   }
296
297
298   public static List<Phyre2SummaryPojo> parsePhyreCrudeList(String crudeList)
299   {
300     List<Phyre2SummaryPojo> phyre2Results = new ArrayList<Phyre2SummaryPojo>();
301     try (BufferedReader br = new BufferedReader(new FileReader(crudeList)))
302     {
303       String line;
304       while ((line = br.readLine()) != null)
305       {
306         String[] lineData = line.split(" ");
307         Phyre2SummaryPojo psp = new Phyre2SummaryPojo();
308         psp.setSerialNo(Integer.valueOf(lineData[0]));
309         psp.setTemplateId(lineData[1]);
310         psp.setConfidence(100 * Double.valueOf(lineData[2]));
311         psp.setPid(Integer.valueOf(lineData[3]));
312         psp.setAlignedRange(lineData[4] + " - " + lineData[5]);
313         // psp.setCoverage(coverage);
314         // psp.setTemplateSummary(templateSummary);
315         phyre2Results.add(psp);
316       }
317     } catch (Exception e)
318     {
319       e.printStackTrace();
320     }
321     return phyre2Results;
322   }
323
324   public static DefaultTableModel getTableModel(
325           List<Phyre2SummaryPojo> phyreResults)
326   {
327     if (phyreResults == null)
328     {
329       return null;
330     }
331     DefaultTableModel tableModel = new DefaultTableModel()
332     {
333       @Override
334       public boolean isCellEditable(int row, int column)
335       {
336         return false;
337       }
338
339       @Override
340       public Class<?> getColumnClass(int columnIndex)
341       {
342         switch (columnIndex)
343         {
344         case 0:
345           return Integer.class;
346         case 1:
347           return String.class;
348         case 2:
349           return String.class;
350         case 3:
351           return String.class;
352         case 4:
353           return Double.class;
354         case 5:
355           return Integer.class;
356         case 6:
357           return String.class;
358         default:
359           return String.class;
360         }
361       }
362
363     };
364
365     tableModel.addColumn("#");
366     tableModel.addColumn("Template");
367     tableModel.addColumn("Aligned Range");
368     tableModel.addColumn("Coverage");
369     tableModel.addColumn("Confidence");
370     tableModel.addColumn("%.i.d");
371     tableModel.addColumn("Template Information");
372
373     for (Phyre2SummaryPojo res : phyreResults)
374     {
375       tableModel.addRow(new Object[] { res.getSerialNo(),
376           res.getTemplateId(), res.getAlignedRange(), res.getCoverage(),
377           res.getConfidence(), res.getPid(), res.getTemplateSummary() }); 
378     }
379     return tableModel;
380   }
381
382   public static void configurePhyreResultTable(JTable phyreResultTable)
383   {
384
385     DecimalFormatTableCellRenderer idCellRender = new DecimalFormatTableCellRenderer(
386             true, 0);
387     DecimalFormatTableCellRenderer pidCellRender = new DecimalFormatTableCellRenderer(
388             true, 1);
389     DecimalFormatTableCellRenderer confidenceCellRender = new DecimalFormatTableCellRenderer(
390             true, 1);
391
392     phyreResultTable.getColumn("#").setMinWidth(20);
393     phyreResultTable.getColumn("#").setPreferredWidth(30);
394     phyreResultTable.getColumn("#").setMaxWidth(40);
395     phyreResultTable.getColumn("#").setCellRenderer(idCellRender);
396
397     phyreResultTable.getColumn("Template").setMinWidth(60);
398     phyreResultTable.getColumn("Template").setPreferredWidth(90);
399     phyreResultTable.getColumn("Template").setMaxWidth(150);
400
401     phyreResultTable.getColumn("Aligned Range").setMinWidth(80);
402     phyreResultTable.getColumn("Aligned Range").setPreferredWidth(80);
403     phyreResultTable.getColumn("Aligned Range").setMaxWidth(120);
404
405     phyreResultTable.getColumn("Coverage").setMinWidth(60);
406     phyreResultTable.getColumn("Coverage").setPreferredWidth(60);
407     phyreResultTable.getColumn("Coverage").setMaxWidth(90);
408
409     phyreResultTable.getColumn("Confidence").setMinWidth(60);
410     phyreResultTable.getColumn("Confidence").setPreferredWidth(60);
411     phyreResultTable.getColumn("Confidence").setMaxWidth(90);
412     phyreResultTable.getColumn("Confidence").setCellRenderer(
413             confidenceCellRender);
414
415     phyreResultTable.getColumn("%.i.d").setMinWidth(45);
416     phyreResultTable.getColumn("%.i.d").setPreferredWidth(450);
417     phyreResultTable.getColumn("%.i.d").setMaxWidth(65);
418     phyreResultTable.getColumn("%.i.d").setCellRenderer(pidCellRender);
419
420     phyreResultTable.getColumn("Template Information").setMinWidth(400);
421     phyreResultTable.getColumn("Template Information").setPreferredWidth(
422             600);
423     phyreResultTable.getColumn("Template Information").setMaxWidth(1500);
424   }
425 }