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